@dxos/react-ui-editor 0.7.5-main.9cb18ac → 0.7.5-main.9d2a38b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +1105 -1127
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1128 -1164
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1105 -1127
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/InputMode.stories.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +4 -0
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/comment.d.ts +17 -0
- package/dist/types/src/components/EditorToolbar/comment.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/headings.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts +3 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts +58 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/viewMode.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/viewMode.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +3 -4
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/editorAction.d.ts +12 -0
- package/dist/types/src/extensions/markdown/editorAction.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +14 -12
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/stack-item-content-class-names.d.ts +3 -0
- package/dist/types/src/styles/stack-item-content-class-names.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +28 -27
- package/src/InputMode.stories.tsx +7 -10
- package/src/components/EditorToolbar/EditorToolbar.tsx +106 -0
- package/src/components/EditorToolbar/blocks.ts +41 -0
- package/src/components/EditorToolbar/comment.ts +20 -0
- package/src/components/EditorToolbar/formatting.ts +41 -0
- package/src/components/EditorToolbar/headings.ts +59 -0
- package/src/components/EditorToolbar/index.ts +6 -0
- package/src/components/EditorToolbar/lists.ts +40 -0
- package/src/components/EditorToolbar/util.ts +65 -0
- package/src/components/EditorToolbar/viewMode.ts +48 -0
- package/src/components/index.ts +1 -1
- package/src/extensions/comments.ts +8 -15
- package/src/extensions/markdown/{action.ts → editorAction.ts} +22 -20
- package/src/extensions/markdown/formatting.ts +20 -24
- package/src/extensions/markdown/index.ts +1 -1
- package/src/extensions/markdown/styles.ts +21 -0
- package/src/hooks/useActionHandler.ts +4 -4
- package/src/index.ts +4 -0
- package/src/styles/stack-item-content-class-names.ts +17 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -34
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/index.d.ts +0 -2
- package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/action.d.ts +0 -9
- package/dist/types/src/extensions/markdown/action.d.ts.map +0 -1
- package/src/components/Toolbar/Toolbar.tsx +0 -522
- package/src/components/Toolbar/index.ts +0 -5
@@ -39,259 +39,856 @@ import { EditorView as EditorView21, keymap as keymap11 } from "@codemirror/view
|
|
39
39
|
import { tags as tags2 } from "@lezer/highlight";
|
40
40
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
41
41
|
|
42
|
-
// packages/ui/react-ui-editor/src/components/
|
43
|
-
import
|
44
|
-
import {
|
45
|
-
import
|
46
|
-
import {
|
47
|
-
import { Button, DropdownMenu, ElevationProvider, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
48
|
-
import { getSize } from "@dxos/react-ui-theme";
|
42
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
43
|
+
import React, { useCallback } from "react";
|
44
|
+
import { ElevationProvider } from "@dxos/react-ui";
|
45
|
+
import { ToolbarMenu, MenuProvider, useMenuActions, createGapSeparator } from "@dxos/react-ui-menu";
|
46
|
+
import { textBlockWidth } from "@dxos/react-ui-theme";
|
49
47
|
|
50
|
-
// packages/ui/react-ui-editor/src/
|
51
|
-
import {
|
52
|
-
import {
|
53
|
-
import {
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
var
|
58
|
-
|
59
|
-
|
60
|
-
|
48
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/util.ts
|
49
|
+
import { useMemo } from "react";
|
50
|
+
import { create } from "@dxos/live-object";
|
51
|
+
import { createMenuAction, createMenuItemGroup } from "@dxos/react-ui-menu";
|
52
|
+
var useEditorToolbarState = (initialState = {}) => {
|
53
|
+
return useMemo(() => create(initialState), []);
|
54
|
+
};
|
55
|
+
var createEditorAction = (payload, icon, label = [
|
56
|
+
`${payload.type} label`,
|
57
|
+
{
|
58
|
+
ns: translationKey
|
61
59
|
}
|
60
|
+
], id = payload.type) => createMenuAction(id, {
|
61
|
+
icon,
|
62
|
+
label,
|
63
|
+
...payload
|
64
|
+
});
|
65
|
+
var createEditorActionGroup = (id, props, icon) => createMenuItemGroup(id, {
|
66
|
+
icon,
|
67
|
+
iconOnly: true,
|
68
|
+
...props
|
62
69
|
});
|
70
|
+
var editorToolbarSearch = createEditorAction({
|
71
|
+
type: "search"
|
72
|
+
}, "ph--magnifying-glass--regular");
|
63
73
|
|
64
|
-
// packages/ui/react-ui-editor/src/
|
65
|
-
var
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
};
|
70
|
-
var
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
74
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/blocks.ts
|
75
|
+
var createBlockGroupAction = (value) => createEditorActionGroup("block", {
|
76
|
+
variant: "toggleGroup",
|
77
|
+
selectCardinality: "single",
|
78
|
+
value
|
79
|
+
});
|
80
|
+
var createBlockActions = (value, blankLine) => Object.entries({
|
81
|
+
blockquote: "ph--quotes--regular",
|
82
|
+
codeblock: "ph--code-block--regular",
|
83
|
+
table: "ph--table--regular"
|
84
|
+
}).map(([type, icon]) => {
|
85
|
+
return createEditorAction({
|
86
|
+
type,
|
87
|
+
checked: type === value,
|
88
|
+
...type === "table" && {
|
89
|
+
disabled: !!blankLine
|
90
|
+
}
|
91
|
+
}, icon);
|
92
|
+
});
|
93
|
+
var createBlocks = (state) => {
|
94
|
+
const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
|
95
|
+
const blockGroupAction = createBlockGroupAction(value);
|
96
|
+
const blockActions = createBlockActions(value, state.blankLine);
|
97
|
+
return {
|
98
|
+
nodes: [
|
99
|
+
blockGroupAction,
|
100
|
+
...blockActions
|
101
|
+
],
|
102
|
+
edges: [
|
103
|
+
{
|
104
|
+
source: "root",
|
105
|
+
target: "block"
|
106
|
+
},
|
107
|
+
...blockActions.map(({ id }) => ({
|
108
|
+
source: blockGroupAction.id,
|
109
|
+
target: id
|
110
|
+
}))
|
111
|
+
]
|
112
|
+
};
|
97
113
|
};
|
98
114
|
|
99
|
-
// packages/ui/react-ui-editor/src/
|
100
|
-
|
101
|
-
var
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
115
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/comment.ts
|
116
|
+
var commentLabel = (comment, selection) => comment ? "selection overlaps existing comment label" : selection === false ? "select text to comment label" : "comment label";
|
117
|
+
var createCommentAction = (label) => createEditorAction({
|
118
|
+
type: "comment",
|
119
|
+
testId: "editor.toolbar.comment"
|
120
|
+
}, "ph--chat-text--regular", label);
|
121
|
+
var createComment = (state) => ({
|
122
|
+
nodes: [
|
123
|
+
createCommentAction(commentLabel(state.comment, state.selection))
|
124
|
+
],
|
125
|
+
edges: [
|
126
|
+
{
|
127
|
+
source: "root",
|
128
|
+
target: "comment"
|
113
129
|
}
|
130
|
+
]
|
131
|
+
});
|
132
|
+
|
133
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/formatting.ts
|
134
|
+
var formats = {
|
135
|
+
strong: "ph--text-b--regular",
|
136
|
+
emphasis: "ph--text-italic--regular",
|
137
|
+
strikethrough: "ph--text-strikethrough--regular",
|
138
|
+
code: "ph--code--regular",
|
139
|
+
link: "ph--link--regular"
|
140
|
+
};
|
141
|
+
var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
|
142
|
+
variant: "toggleGroup",
|
143
|
+
selectCardinality: "multiple",
|
144
|
+
value: Object.keys(formats).filter((key) => !!formatting[key])
|
145
|
+
});
|
146
|
+
var createFormattingActions = (formatting) => Object.entries(formats).map(([type, icon]) => createEditorAction({
|
147
|
+
type,
|
148
|
+
checked: !!formatting[type]
|
149
|
+
}, icon));
|
150
|
+
var createFormatting = (state) => {
|
151
|
+
const formattingGroupAction = createFormattingGroup(state);
|
152
|
+
const formattingActions = createFormattingActions(state);
|
153
|
+
return {
|
154
|
+
nodes: [
|
155
|
+
formattingGroupAction,
|
156
|
+
...formattingActions
|
157
|
+
],
|
158
|
+
edges: [
|
159
|
+
{
|
160
|
+
source: "root",
|
161
|
+
target: "formatting"
|
162
|
+
},
|
163
|
+
...formattingActions.map(({ id }) => ({
|
164
|
+
source: formattingGroupAction.id,
|
165
|
+
target: id
|
166
|
+
}))
|
167
|
+
]
|
114
168
|
};
|
115
169
|
};
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
170
|
+
|
171
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/headings.ts
|
172
|
+
var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
|
173
|
+
variant: "dropdownMenu",
|
174
|
+
applyActive: true,
|
175
|
+
selectCardinality: "single",
|
176
|
+
value
|
177
|
+
}, "ph--text-h--regular");
|
178
|
+
var createHeadingActions = (value) => Object.entries({
|
179
|
+
"0": "ph--paragraph--regular",
|
180
|
+
"1": "ph--text-h-one--regular",
|
181
|
+
"2": "ph--text-h-two--regular",
|
182
|
+
"3": "ph--text-h-three--regular",
|
183
|
+
"4": "ph--text-h-four--regular",
|
184
|
+
"5": "ph--text-h-five--regular",
|
185
|
+
"6": "ph--text-h-six--regular"
|
186
|
+
}).map(([levelStr, icon]) => {
|
187
|
+
const level = parseInt(levelStr);
|
188
|
+
return createEditorAction({
|
189
|
+
type: "heading",
|
190
|
+
data: level,
|
191
|
+
checked: value === levelStr
|
192
|
+
}, icon, [
|
193
|
+
"heading level label",
|
194
|
+
{
|
195
|
+
count: level,
|
196
|
+
ns: translationKey
|
197
|
+
}
|
198
|
+
], `heading--${levelStr}`);
|
199
|
+
});
|
200
|
+
var computeHeadingValue = (state) => {
|
201
|
+
const blockType = state ? state.blockType : "paragraph";
|
202
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
203
|
+
return header ? header[1] : blockType === "paragraph" || !blockType ? "0" : "";
|
127
204
|
};
|
128
|
-
var
|
129
|
-
|
130
|
-
|
205
|
+
var createHeadings = (state) => {
|
206
|
+
const headingValue = computeHeadingValue(state);
|
207
|
+
const headingGroupAction = createHeadingGroupAction(headingValue);
|
208
|
+
const headingActions = createHeadingActions(headingValue);
|
209
|
+
return {
|
210
|
+
nodes: [
|
211
|
+
headingGroupAction,
|
212
|
+
...headingActions
|
213
|
+
],
|
214
|
+
edges: [
|
215
|
+
{
|
216
|
+
source: "root",
|
217
|
+
target: "heading"
|
218
|
+
},
|
219
|
+
...headingActions.map(({ id }) => ({
|
220
|
+
source: headingGroupAction.id,
|
221
|
+
target: id
|
222
|
+
}))
|
223
|
+
]
|
224
|
+
};
|
131
225
|
};
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
226
|
+
|
227
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/lists.ts
|
228
|
+
var listStyles = {
|
229
|
+
bullet: "ph--list-bullets--regular",
|
230
|
+
ordered: "ph--list-numbers--regular",
|
231
|
+
task: "ph--list-checks--regular"
|
232
|
+
};
|
233
|
+
var createListGroupAction = (value) => createEditorActionGroup("list", {
|
234
|
+
variant: "toggleGroup",
|
235
|
+
selectCardinality: "single",
|
236
|
+
value
|
237
|
+
});
|
238
|
+
var createListActions = (value) => Object.entries(listStyles).map(([listStyle, icon]) => createEditorAction({
|
239
|
+
type: `list-${listStyle}`,
|
240
|
+
checked: value === listStyle
|
241
|
+
}, icon));
|
242
|
+
var createLists = (state) => {
|
243
|
+
const value = state.listStyle ?? "";
|
244
|
+
const listGroupAction = createListGroupAction(value);
|
245
|
+
const listActionsMap = createListActions(value);
|
246
|
+
return {
|
247
|
+
nodes: [
|
248
|
+
listGroupAction,
|
249
|
+
...listActionsMap
|
250
|
+
],
|
251
|
+
edges: [
|
252
|
+
{
|
253
|
+
source: "root",
|
254
|
+
target: "list"
|
255
|
+
},
|
256
|
+
...listActionsMap.map(({ id }) => ({
|
257
|
+
source: listGroupAction.id,
|
258
|
+
target: id
|
259
|
+
}))
|
260
|
+
]
|
261
|
+
};
|
262
|
+
};
|
263
|
+
|
264
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/viewMode.ts
|
265
|
+
var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
|
266
|
+
variant: "dropdownMenu",
|
267
|
+
applyActive: true,
|
268
|
+
selectCardinality: "single",
|
269
|
+
value
|
270
|
+
}, "ph--eye--regular");
|
271
|
+
var createViewModeActions = (value) => Object.entries({
|
272
|
+
preview: "ph--eye--regular",
|
273
|
+
source: "ph--pencil-simple--regular",
|
274
|
+
readonly: "ph--pencil-slash--regular"
|
275
|
+
}).map(([viewMode, icon]) => {
|
276
|
+
return createEditorAction({
|
277
|
+
type: "view-mode",
|
278
|
+
data: viewMode,
|
279
|
+
checked: viewMode === value
|
280
|
+
}, icon, [
|
281
|
+
`${viewMode} mode label`,
|
282
|
+
{
|
283
|
+
ns: translationKey
|
136
284
|
}
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
285
|
+
], `view-mode--${viewMode}`);
|
286
|
+
});
|
287
|
+
var createViewMode = (state) => {
|
288
|
+
const value = state.viewMode ?? "source";
|
289
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
290
|
+
const viewModeActions = createViewModeActions(value);
|
291
|
+
return {
|
292
|
+
nodes: [
|
293
|
+
viewModeGroupAction,
|
294
|
+
...viewModeActions
|
295
|
+
],
|
296
|
+
edges: [
|
297
|
+
{
|
298
|
+
source: "root",
|
299
|
+
target: "viewMode"
|
300
|
+
},
|
301
|
+
...viewModeActions.map(({ id }) => ({
|
302
|
+
source: viewModeGroupAction.id,
|
303
|
+
target: id
|
304
|
+
}))
|
305
|
+
]
|
306
|
+
};
|
157
307
|
};
|
158
308
|
|
159
|
-
// packages/ui/react-ui-editor/src/
|
160
|
-
|
161
|
-
|
309
|
+
// packages/ui/react-ui-editor/src/styles/stack-item-content-class-names.ts
|
310
|
+
import { mx } from "@dxos/react-ui-theme";
|
311
|
+
var stackItemContentEditorClassNames = (role) => mx("ch-focus-ring-inset data-[toolbar=disabled]:pbs-2 attention-surface", role === "article" ? "min-bs-0" : "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24");
|
312
|
+
var stackItemContentToolbarClassNames = (role) => mx("attention-surface is-full border-be !border-separator", role === "section" && "sticky block-start-0 z-[1] -mbe-px min-is-0");
|
313
|
+
|
314
|
+
// packages/ui/react-ui-editor/src/components/EditorToolbar/EditorToolbar.tsx
|
315
|
+
var createToolbar = ({ state, customActions, ...features }) => {
|
316
|
+
const nodes = [];
|
317
|
+
const edges = [];
|
318
|
+
if (features.headings ?? true) {
|
319
|
+
const headings2 = createHeadings(state);
|
320
|
+
nodes.push(...headings2.nodes);
|
321
|
+
edges.push(...headings2.edges);
|
322
|
+
}
|
323
|
+
if (features.formatting ?? true) {
|
324
|
+
const formatting = createFormatting(state);
|
325
|
+
nodes.push(...formatting.nodes);
|
326
|
+
edges.push(...formatting.edges);
|
327
|
+
}
|
328
|
+
if (features.lists ?? true) {
|
329
|
+
const lists = createLists(state);
|
330
|
+
nodes.push(...lists.nodes);
|
331
|
+
edges.push(...lists.edges);
|
332
|
+
}
|
333
|
+
if (features.blocks ?? true) {
|
334
|
+
const blocks = createBlocks(state);
|
335
|
+
nodes.push(...blocks.nodes);
|
336
|
+
edges.push(...blocks.edges);
|
337
|
+
}
|
338
|
+
if (customActions) {
|
339
|
+
const custom = customActions();
|
340
|
+
nodes.push(...custom.nodes);
|
341
|
+
edges.push(...custom.edges);
|
342
|
+
}
|
343
|
+
const editorToolbarGap = createGapSeparator();
|
344
|
+
nodes.push(...editorToolbarGap.nodes);
|
345
|
+
edges.push(...editorToolbarGap.edges);
|
346
|
+
if (features.comment ?? true) {
|
347
|
+
const comment = createComment(state);
|
348
|
+
nodes.push(...comment.nodes);
|
349
|
+
edges.push(...comment.edges);
|
350
|
+
}
|
351
|
+
if (features.search ?? true) {
|
352
|
+
nodes.push(editorToolbarSearch);
|
353
|
+
edges.push({
|
354
|
+
source: "root",
|
355
|
+
target: editorToolbarSearch.id
|
356
|
+
});
|
357
|
+
}
|
358
|
+
if (features.viewMode ?? true) {
|
359
|
+
const viewMode = createViewMode(state);
|
360
|
+
nodes.push(...viewMode.nodes);
|
361
|
+
edges.push(...viewMode.edges);
|
362
|
+
}
|
162
363
|
return {
|
163
|
-
|
164
|
-
|
165
|
-
top: rect.top,
|
166
|
-
bottom: rect.bottom
|
364
|
+
nodes,
|
365
|
+
edges
|
167
366
|
};
|
168
367
|
};
|
169
|
-
var
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
return
|
368
|
+
var useEditorToolbarActionGraph = ({ onAction, ...props }) => {
|
369
|
+
const menuCreator = useCallback(() => createToolbar(props), [
|
370
|
+
props
|
371
|
+
]);
|
372
|
+
const { resolveGroupItems } = useMenuActions(menuCreator);
|
373
|
+
return {
|
374
|
+
resolveGroupItems,
|
375
|
+
onAction
|
376
|
+
};
|
175
377
|
};
|
176
|
-
var
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
}
|
182
|
-
|
183
|
-
}
|
378
|
+
var EditorToolbar = ({ classNames, attendableId, role, ...props }) => {
|
379
|
+
const menuProps = useEditorToolbarActionGraph(props);
|
380
|
+
return /* @__PURE__ */ React.createElement("div", {
|
381
|
+
role: "none",
|
382
|
+
className: stackItemContentToolbarClassNames(role)
|
383
|
+
}, /* @__PURE__ */ React.createElement(ElevationProvider, {
|
384
|
+
elevation: role === "section" ? "positioned" : "base"
|
385
|
+
}, /* @__PURE__ */ React.createElement(MenuProvider, {
|
386
|
+
...menuProps,
|
387
|
+
attendableId
|
388
|
+
}, /* @__PURE__ */ React.createElement(ToolbarMenu, {
|
389
|
+
classNames: [
|
390
|
+
textBlockWidth,
|
391
|
+
"!bg-transparent",
|
392
|
+
classNames
|
393
|
+
]
|
394
|
+
}))));
|
184
395
|
};
|
185
396
|
|
186
|
-
// packages/ui/react-ui-editor/src/
|
187
|
-
import
|
188
|
-
import {
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
397
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
398
|
+
import { EditorView } from "@codemirror/view";
|
399
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
400
|
+
|
401
|
+
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
402
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
403
|
+
var headings = {
|
404
|
+
1: "text-4xl",
|
405
|
+
2: "text-3xl",
|
406
|
+
3: "text-2xl",
|
407
|
+
4: "text-xl",
|
408
|
+
5: "text-lg",
|
409
|
+
6: "text-md"
|
410
|
+
};
|
411
|
+
var theme = {
|
412
|
+
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
413
|
+
codeMark: "font-mono text-primary-500",
|
414
|
+
mark: "opacity-50",
|
415
|
+
heading: (level) => {
|
416
|
+
return mx2(headings[level], "dark:text-primary-400");
|
200
417
|
}
|
201
|
-
return el;
|
202
418
|
};
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
419
|
+
|
420
|
+
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
421
|
+
import get from "lodash.get";
|
422
|
+
import { tokens } from "@dxos/react-ui-theme";
|
423
|
+
var getToken = (path, defaultValue) => {
|
424
|
+
const value = get(tokens, path, defaultValue);
|
425
|
+
return value?.toString() ?? "";
|
208
426
|
};
|
427
|
+
var fontBody = getToken("fontFamily.body");
|
428
|
+
var fontMono = getToken("fontFamily.mono");
|
209
429
|
|
210
|
-
// packages/ui/react-ui-editor/src/
|
211
|
-
var
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
}
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
430
|
+
// packages/ui/react-ui-editor/src/styles/theme.ts
|
431
|
+
var defaultTheme = {
|
432
|
+
"&": {},
|
433
|
+
"&.cm-focused": {
|
434
|
+
outline: "none"
|
435
|
+
},
|
436
|
+
/**
|
437
|
+
* Scroller
|
438
|
+
*/
|
439
|
+
".cm-scroller": {
|
440
|
+
overflowY: "auto"
|
441
|
+
},
|
442
|
+
/**
|
443
|
+
* Content
|
444
|
+
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
445
|
+
*/
|
446
|
+
".cm-content": {
|
447
|
+
padding: "unset",
|
448
|
+
fontFamily: fontBody,
|
449
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
450
|
+
fontSize: "16px",
|
451
|
+
lineHeight: 1.5,
|
452
|
+
color: "unset"
|
453
|
+
},
|
454
|
+
/**
|
455
|
+
* Gutters
|
456
|
+
* NOTE: Gutters should have the same top margin as the content.
|
457
|
+
* NOTE: They can't be transparent since the content needs to scroll below.
|
458
|
+
*/
|
459
|
+
".cm-gutters": {
|
460
|
+
background: "var(--surface-bg)",
|
461
|
+
borderRight: "none"
|
462
|
+
},
|
463
|
+
".cm-gutter": {},
|
464
|
+
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
465
|
+
minWidth: "40px",
|
466
|
+
alignContent: "center"
|
467
|
+
},
|
468
|
+
/**
|
469
|
+
* Height is set to match the corresponding line.
|
470
|
+
*/
|
471
|
+
".cm-gutterElement": {
|
472
|
+
alignItems: "center",
|
473
|
+
fontSize: "16px"
|
474
|
+
},
|
475
|
+
/**
|
476
|
+
* Line.
|
477
|
+
*/
|
478
|
+
".cm-line": {
|
479
|
+
paddingInline: 0
|
480
|
+
},
|
481
|
+
".cm-activeLine": {
|
482
|
+
background: "var(--dx-cmActiveLine)"
|
483
|
+
},
|
484
|
+
/**
|
485
|
+
* Cursor (layer).
|
486
|
+
*/
|
487
|
+
".cm-cursor, .cm-dropCursor": {
|
488
|
+
borderLeft: "2px solid var(--dx-cmCursor)"
|
489
|
+
},
|
490
|
+
".cm-placeholder": {
|
491
|
+
color: "var(--dx-subdued)"
|
492
|
+
},
|
493
|
+
/**
|
494
|
+
* Selection (layer).
|
495
|
+
*/
|
496
|
+
".cm-selectionBackground": {
|
497
|
+
background: "var(--dx-cmSelection)"
|
498
|
+
},
|
499
|
+
/**
|
500
|
+
* Search.
|
501
|
+
* NOTE: Matches comment.
|
502
|
+
*/
|
503
|
+
".cm-searchMatch": {
|
504
|
+
margin: "0 -3px",
|
505
|
+
padding: "3px",
|
506
|
+
borderRadius: "3px",
|
507
|
+
background: "var(--dx-cmHighlightSurface)",
|
508
|
+
color: "var(--dx-cmHighlight)"
|
509
|
+
},
|
510
|
+
".cm-searchMatch-selected": {
|
511
|
+
textDecoration: "underline"
|
512
|
+
},
|
513
|
+
/**
|
514
|
+
* Link.
|
515
|
+
*/
|
516
|
+
".cm-link": {
|
517
|
+
textDecorationLine: "underline",
|
518
|
+
textDecorationThickness: "1px",
|
519
|
+
textUnderlineOffset: "2px",
|
520
|
+
borderRadius: ".125rem"
|
521
|
+
},
|
522
|
+
".cm-link > span": {
|
523
|
+
color: "var(--dx-accentText)"
|
524
|
+
},
|
525
|
+
/**
|
526
|
+
* Tooltip.
|
527
|
+
*/
|
528
|
+
".cm-tooltip": {
|
529
|
+
background: "var(--dx-base)"
|
530
|
+
},
|
531
|
+
".cm-tooltip-below": {},
|
532
|
+
/**
|
533
|
+
* Autocomplete.
|
534
|
+
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
535
|
+
*/
|
536
|
+
".cm-tooltip.cm-tooltip-autocomplete": {
|
537
|
+
marginTop: "4px",
|
538
|
+
marginLeft: "-3px"
|
539
|
+
},
|
540
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
541
|
+
maxHeight: "20em"
|
542
|
+
},
|
543
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
544
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
545
|
+
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
546
|
+
paddingLeft: "4px !important",
|
547
|
+
borderBottom: "none !important",
|
548
|
+
color: "var(--dx-accentText)"
|
549
|
+
},
|
550
|
+
".cm-tooltip.cm-completionInfo": {
|
551
|
+
width: "360px !important",
|
552
|
+
margin: "-10px 1px 0 1px",
|
553
|
+
padding: "8px !important",
|
554
|
+
borderColor: "var(--dx-separator)"
|
555
|
+
},
|
556
|
+
".cm-completionIcon": {
|
557
|
+
display: "none"
|
558
|
+
},
|
559
|
+
".cm-completionLabel": {
|
560
|
+
fontFamily: fontBody
|
561
|
+
},
|
562
|
+
".cm-completionMatchedText": {
|
563
|
+
textDecoration: "none !important",
|
564
|
+
opacity: 0.5
|
565
|
+
},
|
566
|
+
/**
|
567
|
+
* Panels
|
568
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
569
|
+
*
|
570
|
+
* Find/replace panel.
|
571
|
+
* <div class="cm-announced">...</div>
|
572
|
+
* <div class="cm-scroller">...</div>
|
573
|
+
* <div class="cm-panels cm-panels-bottom">
|
574
|
+
* <div class="cm-search cm-panel">
|
575
|
+
* <input class="cm-textfield" />
|
576
|
+
* <button class="cm-button">...</button>
|
577
|
+
* <label><input type="checkbox" />...</label>
|
578
|
+
* </div>
|
579
|
+
* </div
|
580
|
+
*/
|
581
|
+
// TODO(burdon): Implement custom panel (with icon buttons).
|
582
|
+
".cm-panels": {},
|
583
|
+
".cm-panel": {
|
584
|
+
fontFamily: fontBody,
|
585
|
+
backgroundColor: "var(--surface-bg)"
|
586
|
+
},
|
587
|
+
".cm-panel input, .cm-panel button, .cm-panel label": {
|
588
|
+
color: "var(--dx-subdued)",
|
589
|
+
fontFamily: fontBody,
|
590
|
+
fontSize: "14px",
|
591
|
+
all: "unset",
|
592
|
+
margin: "3px !important",
|
593
|
+
padding: "2px 6px !important",
|
594
|
+
outline: "1px solid transparent"
|
595
|
+
},
|
596
|
+
".cm-panel input, .cm-panel button": {
|
597
|
+
backgroundColor: "var(--dx-input)"
|
598
|
+
},
|
599
|
+
".cm-panel input:focus, .cm-panel button:focus": {
|
600
|
+
outline: "1px solid var(--dx-accentFocusIndicator)"
|
601
|
+
},
|
602
|
+
".cm-panel label": {
|
603
|
+
display: "inline-flex",
|
604
|
+
alignItems: "center",
|
605
|
+
cursor: "pointer"
|
606
|
+
},
|
607
|
+
".cm-panel input.cm-textfield": {},
|
608
|
+
".cm-panel input[type=checkbox]": {
|
609
|
+
width: "8px",
|
610
|
+
height: "8px",
|
611
|
+
marginRight: "6px !important",
|
612
|
+
padding: "2px !important",
|
613
|
+
color: "var(--dx-accentFocusIndicator)"
|
614
|
+
},
|
615
|
+
".cm-panel button": {
|
616
|
+
"&:hover": {
|
617
|
+
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
618
|
+
},
|
619
|
+
"&:active": {
|
620
|
+
backgroundColor: "var(--dx-accentSurfaceHover)"
|
243
621
|
}
|
244
|
-
}
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
], (state) => {
|
250
|
-
const annotations2 = state.field(annotationsState);
|
251
|
-
const decorations = annotations2.map((annotation) => {
|
252
|
-
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
253
|
-
return range && annotationMark.range(range.from, range.to);
|
254
|
-
}).filter(isNotFalsy);
|
255
|
-
return Decoration.set(decorations);
|
256
|
-
}),
|
257
|
-
styles
|
258
|
-
];
|
622
|
+
},
|
623
|
+
".cm-panel.cm-search": {
|
624
|
+
padding: "4px",
|
625
|
+
borderTop: "1px solid var(--dx-separator)"
|
626
|
+
}
|
259
627
|
};
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
628
|
+
|
629
|
+
// packages/ui/react-ui-editor/src/defaults.ts
|
630
|
+
var margin = "!mt-[1rem]";
|
631
|
+
var editorContent = mx3(margin, "!mli-auto w-full max-w-[min(50rem,100%-2rem)]");
|
632
|
+
var editorFullWidth = mx3(margin);
|
633
|
+
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
634
|
+
var editorGutter = EditorView.theme({
|
635
|
+
// Match margin from content.
|
636
|
+
".cm-gutters": {
|
637
|
+
marginTop: "16px",
|
638
|
+
paddingRight: "1rem"
|
639
|
+
}
|
640
|
+
});
|
641
|
+
var editorMonospace = EditorView.theme({
|
642
|
+
".cm-content": {
|
643
|
+
fontFamily: fontMono
|
265
644
|
}
|
266
645
|
});
|
267
646
|
|
268
|
-
// packages/ui/react-ui-editor/src/extensions/
|
269
|
-
import {
|
270
|
-
import {
|
271
|
-
import {
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
647
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
648
|
+
import { StateField } from "@codemirror/state";
|
649
|
+
import { Decoration, EditorView as EditorView2 } from "@codemirror/view";
|
650
|
+
import { isNotFalsy } from "@dxos/util";
|
651
|
+
|
652
|
+
// packages/ui/react-ui-editor/src/util/facet.ts
|
653
|
+
import { Facet } from "@codemirror/state";
|
654
|
+
var singleValueFacet = (defaultValue) => Facet.define({
|
655
|
+
// Called immediately.
|
656
|
+
combine: (providers) => {
|
657
|
+
return providers[0] ?? defaultValue;
|
658
|
+
}
|
659
|
+
});
|
660
|
+
|
661
|
+
// packages/ui/react-ui-editor/src/util/cursor.ts
|
662
|
+
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
663
|
+
var defaultCursorConverter = {
|
664
|
+
toCursor: (position) => position.toString(),
|
665
|
+
fromCursor: (cursor) => parseInt(cursor)
|
666
|
+
};
|
667
|
+
var Cursor = class _Cursor {
|
668
|
+
static {
|
669
|
+
this.converter = singleValueFacet(defaultCursorConverter);
|
670
|
+
}
|
671
|
+
static {
|
672
|
+
this.getCursorFromRange = (state, range) => {
|
673
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
674
|
+
const from = cursorConverter2.toCursor(range.from);
|
675
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
676
|
+
return [
|
677
|
+
from,
|
678
|
+
to
|
679
|
+
].join(":");
|
680
|
+
};
|
681
|
+
}
|
682
|
+
static {
|
683
|
+
this.getRangeFromCursor = (state, cursor) => {
|
684
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
685
|
+
const parts = cursor.split(":");
|
686
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
687
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
688
|
+
return from !== void 0 && to !== void 0 ? {
|
689
|
+
from,
|
690
|
+
to
|
691
|
+
} : void 0;
|
692
|
+
};
|
693
|
+
}
|
694
|
+
};
|
695
|
+
|
696
|
+
// packages/ui/react-ui-editor/src/util/debug.ts
|
697
|
+
import { log } from "@dxos/log";
|
698
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/debug.ts";
|
699
|
+
var wrapWithCatch = (fn) => {
|
700
|
+
return (...args) => {
|
701
|
+
try {
|
702
|
+
return fn(...args);
|
703
|
+
} catch (err) {
|
704
|
+
log.catch(err, void 0, {
|
705
|
+
F: __dxlog_file,
|
706
|
+
L: 15,
|
707
|
+
S: void 0,
|
708
|
+
C: (f, a) => f(...a)
|
709
|
+
});
|
710
|
+
}
|
711
|
+
};
|
712
|
+
};
|
713
|
+
var callbackWrapper = (fn) => (...args) => {
|
714
|
+
try {
|
715
|
+
return fn(...args);
|
716
|
+
} catch (err) {
|
717
|
+
log.catch(err, void 0, {
|
718
|
+
F: __dxlog_file,
|
719
|
+
L: 29,
|
720
|
+
S: void 0,
|
721
|
+
C: (f, a) => f(...a)
|
722
|
+
});
|
723
|
+
}
|
724
|
+
};
|
725
|
+
var debugDispatcher = (trs, view) => {
|
726
|
+
logChanges(trs);
|
727
|
+
view.update(trs);
|
728
|
+
};
|
729
|
+
var logChanges = (trs) => {
|
730
|
+
const changes = trs.flatMap((tr) => {
|
731
|
+
if (tr.changes.empty) {
|
732
|
+
return void 0;
|
733
|
+
}
|
734
|
+
const changes2 = [];
|
735
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
736
|
+
fromA,
|
737
|
+
toA,
|
738
|
+
fromB,
|
739
|
+
toB,
|
740
|
+
inserted: inserted.toString()
|
741
|
+
})));
|
742
|
+
return changes2;
|
743
|
+
}).filter(Boolean);
|
744
|
+
if (changes.length) {
|
745
|
+
log.info("changes", {
|
746
|
+
changes
|
747
|
+
}, {
|
748
|
+
F: __dxlog_file,
|
749
|
+
L: 62,
|
750
|
+
S: void 0,
|
751
|
+
C: (f, a) => f(...a)
|
752
|
+
});
|
753
|
+
}
|
754
|
+
};
|
755
|
+
|
756
|
+
// packages/ui/react-ui-editor/src/util/dom.ts
|
757
|
+
var flattenRect = (rect, left) => {
|
758
|
+
const x = left ? rect.left : rect.right;
|
759
|
+
return {
|
760
|
+
left: x,
|
761
|
+
right: x,
|
762
|
+
top: rect.top,
|
763
|
+
bottom: rect.bottom
|
764
|
+
};
|
765
|
+
};
|
766
|
+
var scratchRange;
|
767
|
+
var textRange = (node, from, to = from) => {
|
768
|
+
const range = scratchRange || (scratchRange = document.createRange());
|
769
|
+
range.setEnd(node, to);
|
770
|
+
range.setStart(node, from);
|
771
|
+
return range;
|
772
|
+
};
|
773
|
+
var clientRectsFor = (dom) => {
|
774
|
+
if (dom.nodeType === 3) {
|
775
|
+
return textRange(dom, 0, dom.nodeValue.length).getClientRects();
|
776
|
+
} else if (dom.nodeType === 1) {
|
777
|
+
return dom.getClientRects();
|
778
|
+
} else {
|
779
|
+
return [];
|
780
|
+
}
|
781
|
+
};
|
782
|
+
|
783
|
+
// packages/ui/react-ui-editor/src/util/react.tsx
|
784
|
+
import React2 from "react";
|
785
|
+
import { createRoot } from "react-dom/client";
|
786
|
+
import { ThemeProvider } from "@dxos/react-ui";
|
787
|
+
import { defaultTx } from "@dxos/react-ui-theme";
|
788
|
+
var createElement = (tag, options, children) => {
|
789
|
+
const el = document.createElement(tag);
|
790
|
+
if (options?.className) {
|
791
|
+
el.className = options.className;
|
792
|
+
}
|
793
|
+
if (children) {
|
794
|
+
el.append(...Array.isArray(children) ? children : [
|
795
|
+
children
|
796
|
+
]);
|
797
|
+
}
|
798
|
+
return el;
|
799
|
+
};
|
800
|
+
var renderRoot = (root, node) => {
|
801
|
+
createRoot(root).render(/* @__PURE__ */ React2.createElement(ThemeProvider, {
|
802
|
+
tx: defaultTx
|
803
|
+
}, node));
|
804
|
+
return root;
|
805
|
+
};
|
806
|
+
|
807
|
+
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
808
|
+
var annotationMark = Decoration.mark({
|
809
|
+
class: "cm-annotation"
|
810
|
+
});
|
811
|
+
var annotations = (options = {}) => {
|
812
|
+
const match = (state) => {
|
813
|
+
const annotations2 = [];
|
814
|
+
const text = state.doc.toString();
|
815
|
+
if (options.match) {
|
816
|
+
const matches = text.matchAll(options.match);
|
817
|
+
for (const match2 of matches) {
|
818
|
+
const from = match2.index;
|
819
|
+
const to = from + match2[0].length;
|
820
|
+
const cursor = Cursor.getCursorFromRange(state, {
|
821
|
+
from,
|
822
|
+
to
|
823
|
+
});
|
824
|
+
annotations2.push({
|
825
|
+
cursor
|
826
|
+
});
|
827
|
+
}
|
828
|
+
}
|
829
|
+
return annotations2;
|
830
|
+
};
|
831
|
+
const annotationsState = StateField.define({
|
832
|
+
create: (state) => {
|
833
|
+
return match(state);
|
834
|
+
},
|
835
|
+
update: (value, tr) => {
|
836
|
+
if (!tr.changes.empty) {
|
837
|
+
return match(tr.state);
|
838
|
+
}
|
839
|
+
return value;
|
840
|
+
}
|
841
|
+
});
|
842
|
+
return [
|
843
|
+
annotationsState,
|
844
|
+
EditorView2.decorations.compute([
|
845
|
+
annotationsState
|
846
|
+
], (state) => {
|
847
|
+
const annotations2 = state.field(annotationsState);
|
848
|
+
const decorations = annotations2.map((annotation) => {
|
849
|
+
const range = Cursor.getRangeFromCursor(state, annotation.cursor);
|
850
|
+
return range && annotationMark.range(range.from, range.to);
|
851
|
+
}).filter(isNotFalsy);
|
852
|
+
return Decoration.set(decorations);
|
853
|
+
}),
|
854
|
+
styles
|
855
|
+
];
|
856
|
+
};
|
857
|
+
var styles = EditorView2.theme({
|
858
|
+
".cm-annotation": {
|
859
|
+
textDecoration: "underline",
|
860
|
+
textDecorationStyle: "wavy",
|
861
|
+
textDecorationColor: "var(--dx-error)"
|
862
|
+
}
|
863
|
+
});
|
864
|
+
|
865
|
+
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
866
|
+
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
867
|
+
import { markdownLanguage } from "@codemirror/lang-markdown";
|
868
|
+
import { keymap } from "@codemirror/view";
|
869
|
+
var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
870
|
+
const extensions = [
|
871
|
+
// https://codemirror.net/docs/ref/#view.keymap
|
872
|
+
// https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
|
873
|
+
// TODO(burdon): Set custom keymap.
|
874
|
+
keymap.of(completionKeymap),
|
875
|
+
// https://codemirror.net/examples/autocompletion
|
876
|
+
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
877
|
+
autocompletion({
|
878
|
+
activateOnTyping,
|
879
|
+
override,
|
880
|
+
closeOnBlur: !debug,
|
881
|
+
tooltipClass: () => "shadow rounded"
|
882
|
+
})
|
883
|
+
];
|
884
|
+
if (onSearch) {
|
885
|
+
extensions.push(
|
886
|
+
// TODO(burdon): Optional decoration via addToOptions
|
887
|
+
markdownLanguage.data.of({
|
888
|
+
autocomplete: (context) => {
|
889
|
+
const match = context.matchBefore(/\w*/);
|
890
|
+
if (!match || match.from === match.to && !context.explicit) {
|
891
|
+
return null;
|
295
892
|
}
|
296
893
|
return {
|
297
894
|
from: match.from,
|
@@ -306,7 +903,7 @@ var autocomplete = ({ debug, activateOnTyping, override, onSearch } = {}) => {
|
|
306
903
|
|
307
904
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
308
905
|
import { StateField as StateField2 } from "@codemirror/state";
|
309
|
-
import { EditorView as
|
906
|
+
import { EditorView as EditorView3, ViewPlugin } from "@codemirror/view";
|
310
907
|
import { next as A3 } from "@dxos/automerge/automerge";
|
311
908
|
|
312
909
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
@@ -590,7 +1187,7 @@ var automerge = (accessor) => {
|
|
590
1187
|
}
|
591
1188
|
}),
|
592
1189
|
// Reconcile local updates.
|
593
|
-
|
1190
|
+
EditorView3.updateListener.of(({ view, changes }) => {
|
594
1191
|
if (!changes.empty) {
|
595
1192
|
syncer.reconcile(view, true);
|
596
1193
|
}
|
@@ -600,7 +1197,7 @@ var automerge = (accessor) => {
|
|
600
1197
|
|
601
1198
|
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
602
1199
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
603
|
-
import { Decoration as Decoration2, EditorView as
|
1200
|
+
import { Decoration as Decoration2, EditorView as EditorView4, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
604
1201
|
import { Event } from "@dxos/async";
|
605
1202
|
import { Context } from "@dxos/context";
|
606
1203
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts";
|
@@ -774,7 +1371,7 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
774
1371
|
return true;
|
775
1372
|
}
|
776
1373
|
};
|
777
|
-
var styles2 =
|
1374
|
+
var styles2 = EditorView4.theme({
|
778
1375
|
".cm-collab-selection": {},
|
779
1376
|
".cm-collab-selectionLine": {
|
780
1377
|
padding: 0,
|
@@ -940,7 +1537,7 @@ var SpaceAwarenessProvider = class {
|
|
940
1537
|
};
|
941
1538
|
|
942
1539
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
943
|
-
import { EditorView as
|
1540
|
+
import { EditorView as EditorView5, keymap as keymap2 } from "@codemirror/view";
|
944
1541
|
import defaultsDeep from "lodash.defaultsdeep";
|
945
1542
|
import { invariant as invariant2 } from "@dxos/invariant";
|
946
1543
|
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
@@ -988,7 +1585,7 @@ var blast = (options = defaultOptions) => {
|
|
988
1585
|
};
|
989
1586
|
return [
|
990
1587
|
// Cursor moved.
|
991
|
-
|
1588
|
+
EditorView5.updateListener.of((update2) => {
|
992
1589
|
if (blaster?.node !== update2.view.scrollDOM) {
|
993
1590
|
if (blaster) {
|
994
1591
|
blaster.destroy();
|
@@ -1250,11 +1847,11 @@ var random = (min, max) => {
|
|
1250
1847
|
};
|
1251
1848
|
|
1252
1849
|
// packages/ui/react-ui-editor/src/extensions/command/command.ts
|
1253
|
-
import { EditorView as
|
1850
|
+
import { EditorView as EditorView7, keymap as keymap3 } from "@codemirror/view";
|
1254
1851
|
|
1255
1852
|
// packages/ui/react-ui-editor/src/extensions/command/hint.ts
|
1256
1853
|
import { RangeSetBuilder } from "@codemirror/state";
|
1257
|
-
import { Decoration as Decoration3, EditorView as
|
1854
|
+
import { Decoration as Decoration3, EditorView as EditorView6, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
|
1258
1855
|
|
1259
1856
|
// packages/ui/react-ui-editor/src/extensions/command/state.ts
|
1260
1857
|
import { StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
|
@@ -1420,7 +2017,7 @@ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
|
|
1420
2017
|
}
|
1421
2018
|
}, {
|
1422
2019
|
provide: (plugin) => [
|
1423
|
-
|
2020
|
+
EditorView6.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
|
1424
2021
|
]
|
1425
2022
|
});
|
1426
2023
|
|
@@ -1431,7 +2028,7 @@ var command = (options) => {
|
|
1431
2028
|
commandState,
|
1432
2029
|
keymap3.of(commandKeyBindings),
|
1433
2030
|
hintViewPlugin(options),
|
1434
|
-
|
2031
|
+
EditorView7.focusChangeEffect.of((_, focusing) => {
|
1435
2032
|
return focusing ? closeEffect.of(null) : null;
|
1436
2033
|
})
|
1437
2034
|
];
|
@@ -1440,16 +2037,16 @@ var command = (options) => {
|
|
1440
2037
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
1441
2038
|
import { invertedEffects } from "@codemirror/commands";
|
1442
2039
|
import { StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
|
1443
|
-
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as
|
2040
|
+
import { hoverTooltip, keymap as keymap5, Decoration as Decoration4, EditorView as EditorView9, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
1444
2041
|
import sortBy from "lodash.sortby";
|
1445
|
-
import { useEffect, useMemo
|
2042
|
+
import { useEffect, useMemo as useMemo2 } from "react";
|
1446
2043
|
import { debounce as debounce2 } from "@dxos/async";
|
1447
2044
|
import { log as log4 } from "@dxos/log";
|
1448
2045
|
import { nonNullable } from "@dxos/util";
|
1449
2046
|
|
1450
2047
|
// packages/ui/react-ui-editor/src/extensions/selection.ts
|
1451
2048
|
import { Transaction } from "@codemirror/state";
|
1452
|
-
import { EditorView as
|
2049
|
+
import { EditorView as EditorView8, keymap as keymap4 } from "@codemirror/view";
|
1453
2050
|
import { debounce } from "@dxos/async";
|
1454
2051
|
import { invariant as invariant3 } from "@dxos/invariant";
|
1455
2052
|
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
@@ -1460,7 +2057,7 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
1460
2057
|
return {
|
1461
2058
|
selection,
|
1462
2059
|
scrollIntoView: !scrollTo,
|
1463
|
-
effects: scrollTo ?
|
2060
|
+
effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
|
1464
2061
|
yMargin: 96
|
1465
2062
|
}) : void 0,
|
1466
2063
|
annotations: Transaction.userEvent.of(stateRestoreAnnotation)
|
@@ -1502,7 +2099,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
1502
2099
|
// setStateDebounced(id, {});
|
1503
2100
|
// },
|
1504
2101
|
// }),
|
1505
|
-
|
2102
|
+
EditorView8.updateListener.of(({ view, transactions }) => {
|
1506
2103
|
const id = view.state.facet(documentId);
|
1507
2104
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
1508
2105
|
return;
|
@@ -1583,7 +2180,7 @@ var commentsState = StateField4.define({
|
|
1583
2180
|
return value;
|
1584
2181
|
}
|
1585
2182
|
});
|
1586
|
-
var styles3 =
|
2183
|
+
var styles3 = EditorView9.theme({
|
1587
2184
|
".cm-comment, .cm-comment-current": {
|
1588
2185
|
margin: "0 -3px",
|
1589
2186
|
padding: "3px",
|
@@ -1603,7 +2200,7 @@ var createCommentMark = (id, isCurrent) => Decoration4.mark({
|
|
1603
2200
|
"data-comment-id": id
|
1604
2201
|
}
|
1605
2202
|
});
|
1606
|
-
var commentsDecorations =
|
2203
|
+
var commentsDecorations = EditorView9.decorations.compute([
|
1607
2204
|
commentsState
|
1608
2205
|
], (state) => {
|
1609
2206
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
@@ -1612,7 +2209,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1612
2209
|
if (!range) {
|
1613
2210
|
log4.warn("Invalid range:", range, {
|
1614
2211
|
F: __dxlog_file7,
|
1615
|
-
L:
|
2212
|
+
L: 144,
|
1616
2213
|
S: void 0,
|
1617
2214
|
C: (f, a) => f(...a)
|
1618
2215
|
});
|
@@ -1626,7 +2223,7 @@ var commentsDecorations = EditorView8.decorations.compute([
|
|
1626
2223
|
return Decoration4.set(decorations);
|
1627
2224
|
});
|
1628
2225
|
var commentClickedEffect = StateEffect3.define();
|
1629
|
-
var handleCommentClick =
|
2226
|
+
var handleCommentClick = EditorView9.domEventHandlers({
|
1630
2227
|
click: (event, view) => {
|
1631
2228
|
let target = event.target;
|
1632
2229
|
const editorRoot = view.dom;
|
@@ -1665,7 +2262,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1665
2262
|
}
|
1666
2263
|
};
|
1667
2264
|
return [
|
1668
|
-
|
2265
|
+
EditorView9.domEventHandlers({
|
1669
2266
|
cut: handleTrack,
|
1670
2267
|
copy: handleTrack
|
1671
2268
|
}),
|
@@ -1687,7 +2284,7 @@ var trackPastedComments = (onUpdate) => {
|
|
1687
2284
|
return effects;
|
1688
2285
|
}),
|
1689
2286
|
// Handle paste or the undo of comment deletion.
|
1690
|
-
|
2287
|
+
EditorView9.updateListener.of((update2) => {
|
1691
2288
|
const restore = [];
|
1692
2289
|
for (let i = 0; i < update2.transactions.length; i++) {
|
1693
2290
|
const tr = update2.transactions[i];
|
@@ -1746,7 +2343,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
1746
2343
|
var restoreCommentEffect = StateEffect3.define({
|
1747
2344
|
map: mapTrackedComment
|
1748
2345
|
});
|
1749
|
-
var
|
2346
|
+
var createComment2 = (view) => {
|
1750
2347
|
const options = view.state.facet(optionsFacet);
|
1751
2348
|
const { from, to } = view.state.selection.main;
|
1752
2349
|
if (from === to) {
|
@@ -1791,7 +2388,7 @@ var comments = (options = {}) => {
|
|
1791
2388
|
options.onCreate && keymap5.of([
|
1792
2389
|
{
|
1793
2390
|
key: shortcut,
|
1794
|
-
run: callbackWrapper(
|
2391
|
+
run: callbackWrapper(createComment2)
|
1795
2392
|
}
|
1796
2393
|
]),
|
1797
2394
|
//
|
@@ -1827,7 +2424,7 @@ var comments = (options = {}) => {
|
|
1827
2424
|
//
|
1828
2425
|
// Track deleted ranges and update ranges for decorations.
|
1829
2426
|
//
|
1830
|
-
|
2427
|
+
EditorView9.updateListener.of(({ view, state, changes }) => {
|
1831
2428
|
let mod = false;
|
1832
2429
|
const { comments: comments2, ...value } = state.field(commentsState);
|
1833
2430
|
changes.iterChanges((from, to, from2, to2) => {
|
@@ -1859,7 +2456,7 @@ var comments = (options = {}) => {
|
|
1859
2456
|
//
|
1860
2457
|
// Track selection/proximity.
|
1861
2458
|
//
|
1862
|
-
|
2459
|
+
EditorView9.updateListener.of(({ view, state }) => {
|
1863
2460
|
let min = Infinity;
|
1864
2461
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
1865
2462
|
const { head } = state.selection.main;
|
@@ -1913,7 +2510,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1913
2510
|
anchor: range.from
|
1914
2511
|
} : void 0,
|
1915
2512
|
effects: [
|
1916
|
-
needsScroll ?
|
2513
|
+
needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
|
1917
2514
|
y: "center"
|
1918
2515
|
} : void 0) : [],
|
1919
2516
|
needsSelectionUpdate ? setSelection.of({
|
@@ -1924,415 +2521,179 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
1924
2521
|
}
|
1925
2522
|
}
|
1926
2523
|
};
|
1927
|
-
var selectionOverlapsComment = (state) => {
|
1928
|
-
const commentState = state.field(commentsState, false);
|
1929
|
-
if (commentState === void 0) {
|
1930
|
-
return false;
|
1931
|
-
}
|
1932
|
-
const { selection } = state;
|
1933
|
-
for (const range of selection.ranges) {
|
1934
|
-
if (commentState.comments.some(({ range: commentRange }) => overlap(commentRange, range))) {
|
1935
|
-
return true;
|
1936
|
-
}
|
1937
|
-
}
|
1938
|
-
return false;
|
1939
|
-
};
|
1940
|
-
var hasActiveSelection = (state) => {
|
1941
|
-
return state.selection.ranges.some((range) => !range.empty);
|
1942
|
-
};
|
1943
|
-
var ExternalCommentSync = class {
|
1944
|
-
constructor(view, id, subscribe, getComments) {
|
1945
|
-
this.destroy = () => {
|
1946
|
-
this.unsubscribe();
|
1947
|
-
};
|
1948
|
-
const updateComments = () => {
|
1949
|
-
const comments2 = getComments();
|
1950
|
-
if (id === view.state.facet(documentId)) {
|
1951
|
-
queueMicrotask(() => view.dispatch({
|
1952
|
-
effects: setComments.of({
|
1953
|
-
id,
|
1954
|
-
comments: comments2
|
1955
|
-
})
|
1956
|
-
}));
|
1957
|
-
}
|
1958
|
-
};
|
1959
|
-
this.unsubscribe = subscribe(updateComments);
|
1960
|
-
}
|
1961
|
-
};
|
1962
|
-
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin4.fromClass(class {
|
1963
|
-
constructor(view) {
|
1964
|
-
return new ExternalCommentSync(view, id, subscribe, getComments);
|
1965
|
-
}
|
1966
|
-
});
|
1967
|
-
var useCommentState = () => {
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
if (id === view.state.facet(documentId)) {
|
1989
|
-
view.dispatch({
|
1990
|
-
effects: setComments.of({
|
1991
|
-
id,
|
1992
|
-
comments: comments2 ?? []
|
1993
|
-
})
|
1994
|
-
});
|
1995
|
-
}
|
1996
|
-
}
|
1997
|
-
});
|
1998
|
-
};
|
1999
|
-
var useCommentClickListener = (onCommentClick) => {
|
2000
|
-
return useMemo(() => EditorView8.updateListener.of((update2) => {
|
2001
|
-
update2.transactions.forEach((transaction) => {
|
2002
|
-
transaction.effects.forEach((effect) => {
|
2003
|
-
if (effect.is(commentClickedEffect)) {
|
2004
|
-
onCommentClick(effect.value);
|
2005
|
-
}
|
2006
|
-
});
|
2007
|
-
});
|
2008
|
-
}), [
|
2009
|
-
onCommentClick
|
2010
|
-
]);
|
2011
|
-
};
|
2012
|
-
|
2013
|
-
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2014
|
-
import { syntaxTree } from "@codemirror/language";
|
2015
|
-
import { StateField as StateField5 } from "@codemirror/state";
|
2016
|
-
var debugNodeLogger = (log8 = console.log) => {
|
2017
|
-
const logTokens = (state) => syntaxTree(state).iterate({
|
2018
|
-
enter: (node) => log8(node.type)
|
2019
|
-
});
|
2020
|
-
return StateField5.define({
|
2021
|
-
create: (state) => logTokens(state),
|
2022
|
-
update: (_, tr) => logTokens(tr.state)
|
2023
|
-
});
|
2024
|
-
};
|
2025
|
-
|
2026
|
-
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2027
|
-
import { dropCursor, EditorView as EditorView9 } from "@codemirror/view";
|
2028
|
-
var styles4 = EditorView9.theme({
|
2029
|
-
".cm-dropCursor": {
|
2030
|
-
borderLeft: "2px solid var(--dx-accentText)",
|
2031
|
-
color: "var(--dx-accentText)",
|
2032
|
-
padding: "0 4px"
|
2033
|
-
},
|
2034
|
-
".cm-dropCursor:after": {
|
2035
|
-
content: '"\u2190"'
|
2036
|
-
}
|
2037
|
-
});
|
2038
|
-
var dropFile = (options = {}) => {
|
2039
|
-
return [
|
2040
|
-
styles4,
|
2041
|
-
dropCursor(),
|
2042
|
-
EditorView9.domEventHandlers({
|
2043
|
-
drop: (event, view) => {
|
2044
|
-
event.preventDefault();
|
2045
|
-
const files = event.dataTransfer?.files;
|
2046
|
-
const pos = view.posAtCoords(event);
|
2047
|
-
if (files?.length && pos !== null) {
|
2048
|
-
view.dispatch({
|
2049
|
-
selection: {
|
2050
|
-
anchor: pos
|
2051
|
-
}
|
2052
|
-
});
|
2053
|
-
options.onDrop?.(view, {
|
2054
|
-
files
|
2055
|
-
});
|
2056
|
-
}
|
2057
|
-
}
|
2058
|
-
})
|
2059
|
-
];
|
2060
|
-
};
|
2061
|
-
|
2062
|
-
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2063
|
-
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2064
|
-
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2065
|
-
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2066
|
-
import { searchKeymap } from "@codemirror/search";
|
2067
|
-
import { EditorState } from "@codemirror/state";
|
2068
|
-
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2069
|
-
import { EditorView as EditorView11, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2070
|
-
import defaultsDeep2 from "lodash.defaultsdeep";
|
2071
|
-
import merge from "lodash.merge";
|
2072
|
-
import { generateName } from "@dxos/display-name";
|
2073
|
-
import { log as log5 } from "@dxos/log";
|
2074
|
-
import { hueTokens } from "@dxos/react-ui-theme";
|
2075
|
-
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2076
|
-
|
2077
|
-
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2078
|
-
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2079
|
-
import { EditorView as EditorView10 } from "@codemirror/view";
|
2080
|
-
var focusEffect = StateEffect4.define();
|
2081
|
-
var focusField = StateField6.define({
|
2082
|
-
create: () => false,
|
2083
|
-
update: (value, tr) => {
|
2084
|
-
for (const effect of tr.effects) {
|
2085
|
-
if (effect.is(focusEffect)) {
|
2086
|
-
return effect.value;
|
2087
|
-
}
|
2088
|
-
}
|
2089
|
-
return value;
|
2090
|
-
}
|
2091
|
-
});
|
2092
|
-
var focus = [
|
2093
|
-
focusField,
|
2094
|
-
EditorView10.domEventHandlers({
|
2095
|
-
focus: (event, view) => {
|
2096
|
-
setTimeout(() => view.dispatch({
|
2097
|
-
effects: focusEffect.of(true)
|
2098
|
-
}));
|
2099
|
-
},
|
2100
|
-
blur: (event, view) => {
|
2101
|
-
setTimeout(() => view.dispatch({
|
2102
|
-
effects: focusEffect.of(false)
|
2103
|
-
}));
|
2104
|
-
}
|
2105
|
-
})
|
2106
|
-
];
|
2107
|
-
|
2108
|
-
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
2109
|
-
import { mx } from "@dxos/react-ui-theme";
|
2110
|
-
var headings = {
|
2111
|
-
1: "text-4xl",
|
2112
|
-
2: "text-3xl",
|
2113
|
-
3: "text-2xl",
|
2114
|
-
4: "text-xl",
|
2115
|
-
5: "text-lg",
|
2116
|
-
6: "text-md"
|
2117
|
-
};
|
2118
|
-
var theme = {
|
2119
|
-
code: "font-mono !no-underline text-neutral-700 dark:text-neutral-300",
|
2120
|
-
codeMark: "font-mono text-primary-500",
|
2121
|
-
mark: "opacity-50",
|
2122
|
-
heading: (level) => {
|
2123
|
-
return mx(headings[level], "dark:text-primary-400");
|
2124
|
-
}
|
2125
|
-
};
|
2126
|
-
|
2127
|
-
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
2128
|
-
import get from "lodash.get";
|
2129
|
-
import { tokens } from "@dxos/react-ui-theme";
|
2130
|
-
var getToken = (path, defaultValue) => {
|
2131
|
-
const value = get(tokens, path, defaultValue);
|
2132
|
-
return value?.toString() ?? "";
|
2133
|
-
};
|
2134
|
-
var fontBody = getToken("fontFamily.body");
|
2135
|
-
var fontMono = getToken("fontFamily.mono");
|
2136
|
-
|
2137
|
-
// packages/ui/react-ui-editor/src/styles/theme.ts
|
2138
|
-
var defaultTheme = {
|
2139
|
-
"&": {},
|
2140
|
-
"&.cm-focused": {
|
2141
|
-
outline: "none"
|
2142
|
-
},
|
2143
|
-
/**
|
2144
|
-
* Scroller
|
2145
|
-
*/
|
2146
|
-
".cm-scroller": {
|
2147
|
-
overflowY: "auto"
|
2148
|
-
},
|
2149
|
-
/**
|
2150
|
-
* Content
|
2151
|
-
* NOTE: Apply margins to content so that scrollbar is at the edge of the container.
|
2152
|
-
*/
|
2153
|
-
".cm-content": {
|
2154
|
-
padding: "unset",
|
2155
|
-
fontFamily: fontBody,
|
2156
|
-
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
2157
|
-
fontSize: "16px",
|
2158
|
-
lineHeight: 1.5,
|
2159
|
-
color: "unset"
|
2160
|
-
},
|
2161
|
-
/**
|
2162
|
-
* Gutters
|
2163
|
-
* NOTE: Gutters should have the same top margin as the content.
|
2164
|
-
* NOTE: They can't be transparent since the content needs to scroll below.
|
2165
|
-
*/
|
2166
|
-
".cm-gutters": {
|
2167
|
-
background: "var(--surface-bg)",
|
2168
|
-
borderRight: "none"
|
2169
|
-
},
|
2170
|
-
".cm-gutter": {},
|
2171
|
-
".cm-gutter.cm-lineNumbers .cm-gutterElement": {
|
2172
|
-
minWidth: "40px",
|
2173
|
-
alignContent: "center"
|
2174
|
-
},
|
2175
|
-
/**
|
2176
|
-
* Height is set to match the corresponding line.
|
2177
|
-
*/
|
2178
|
-
".cm-gutterElement": {
|
2179
|
-
alignItems: "center",
|
2180
|
-
fontSize: "16px"
|
2181
|
-
},
|
2182
|
-
/**
|
2183
|
-
* Line.
|
2184
|
-
*/
|
2185
|
-
".cm-line": {
|
2186
|
-
paddingInline: 0
|
2187
|
-
},
|
2188
|
-
".cm-activeLine": {
|
2189
|
-
background: "var(--dx-cmActiveLine)"
|
2190
|
-
},
|
2191
|
-
/**
|
2192
|
-
* Cursor (layer).
|
2193
|
-
*/
|
2194
|
-
".cm-cursor, .cm-dropCursor": {
|
2195
|
-
borderLeft: "2px solid var(--dx-cmCursor)"
|
2196
|
-
},
|
2197
|
-
".cm-placeholder": {
|
2198
|
-
color: "var(--dx-subdued)"
|
2199
|
-
},
|
2200
|
-
/**
|
2201
|
-
* Selection (layer).
|
2202
|
-
*/
|
2203
|
-
".cm-selectionBackground": {
|
2204
|
-
background: "var(--dx-cmSelection)"
|
2205
|
-
},
|
2206
|
-
/**
|
2207
|
-
* Search.
|
2208
|
-
* NOTE: Matches comment.
|
2209
|
-
*/
|
2210
|
-
".cm-searchMatch": {
|
2211
|
-
margin: "0 -3px",
|
2212
|
-
padding: "3px",
|
2213
|
-
borderRadius: "3px",
|
2214
|
-
background: "var(--dx-cmHighlightSurface)",
|
2215
|
-
color: "var(--dx-cmHighlight)"
|
2216
|
-
},
|
2217
|
-
".cm-searchMatch-selected": {
|
2218
|
-
textDecoration: "underline"
|
2219
|
-
},
|
2220
|
-
/**
|
2221
|
-
* Link.
|
2222
|
-
*/
|
2223
|
-
".cm-link": {
|
2224
|
-
textDecorationLine: "underline",
|
2225
|
-
textDecorationThickness: "1px",
|
2226
|
-
textUnderlineOffset: "2px",
|
2227
|
-
borderRadius: ".125rem"
|
2228
|
-
},
|
2229
|
-
".cm-link > span": {
|
2230
|
-
color: "var(--dx-accentText)"
|
2231
|
-
},
|
2232
|
-
/**
|
2233
|
-
* Tooltip.
|
2234
|
-
*/
|
2235
|
-
".cm-tooltip": {
|
2236
|
-
background: "var(--dx-base)"
|
2237
|
-
},
|
2238
|
-
".cm-tooltip-below": {},
|
2239
|
-
/**
|
2240
|
-
* Autocomplete.
|
2241
|
-
* https://github.com/codemirror/autocomplete/blob/main/src/completion.ts
|
2242
|
-
*/
|
2243
|
-
".cm-tooltip.cm-tooltip-autocomplete": {
|
2244
|
-
marginTop: "4px",
|
2245
|
-
marginLeft: "-3px"
|
2246
|
-
},
|
2247
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
2248
|
-
maxHeight: "20em"
|
2249
|
-
},
|
2250
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {},
|
2251
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {},
|
2252
|
-
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
2253
|
-
paddingLeft: "4px !important",
|
2254
|
-
borderBottom: "none !important",
|
2255
|
-
color: "var(--dx-accentText)"
|
2256
|
-
},
|
2257
|
-
".cm-tooltip.cm-completionInfo": {
|
2258
|
-
width: "360px !important",
|
2259
|
-
margin: "-10px 1px 0 1px",
|
2260
|
-
padding: "8px !important",
|
2261
|
-
borderColor: "var(--dx-separator)"
|
2262
|
-
},
|
2263
|
-
".cm-completionIcon": {
|
2264
|
-
display: "none"
|
2265
|
-
},
|
2266
|
-
".cm-completionLabel": {
|
2267
|
-
fontFamily: fontBody
|
2268
|
-
},
|
2269
|
-
".cm-completionMatchedText": {
|
2270
|
-
textDecoration: "none !important",
|
2271
|
-
opacity: 0.5
|
2272
|
-
},
|
2273
|
-
/**
|
2274
|
-
* Panels
|
2275
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
2276
|
-
*
|
2277
|
-
* Find/replace panel.
|
2278
|
-
* <div class="cm-announced">...</div>
|
2279
|
-
* <div class="cm-scroller">...</div>
|
2280
|
-
* <div class="cm-panels cm-panels-bottom">
|
2281
|
-
* <div class="cm-search cm-panel">
|
2282
|
-
* <input class="cm-textfield" />
|
2283
|
-
* <button class="cm-button">...</button>
|
2284
|
-
* <label><input type="checkbox" />...</label>
|
2285
|
-
* </div>
|
2286
|
-
* </div
|
2287
|
-
*/
|
2288
|
-
// TODO(burdon): Implement custom panel (with icon buttons).
|
2289
|
-
".cm-panels": {},
|
2290
|
-
".cm-panel": {
|
2291
|
-
fontFamily: fontBody,
|
2292
|
-
backgroundColor: "var(--surface-bg)"
|
2293
|
-
},
|
2294
|
-
".cm-panel input, .cm-panel button, .cm-panel label": {
|
2295
|
-
color: "var(--dx-subdued)",
|
2296
|
-
fontFamily: fontBody,
|
2297
|
-
fontSize: "14px",
|
2298
|
-
all: "unset",
|
2299
|
-
margin: "3px !important",
|
2300
|
-
padding: "2px 6px !important",
|
2301
|
-
outline: "1px solid transparent"
|
2302
|
-
},
|
2303
|
-
".cm-panel input, .cm-panel button": {
|
2304
|
-
backgroundColor: "var(--dx-input)"
|
2305
|
-
},
|
2306
|
-
".cm-panel input:focus, .cm-panel button:focus": {
|
2307
|
-
outline: "1px solid var(--dx-accentFocusIndicator)"
|
2308
|
-
},
|
2309
|
-
".cm-panel label": {
|
2310
|
-
display: "inline-flex",
|
2311
|
-
alignItems: "center",
|
2312
|
-
cursor: "pointer"
|
2313
|
-
},
|
2314
|
-
".cm-panel input.cm-textfield": {},
|
2315
|
-
".cm-panel input[type=checkbox]": {
|
2316
|
-
width: "8px",
|
2317
|
-
height: "8px",
|
2318
|
-
marginRight: "6px !important",
|
2319
|
-
padding: "2px !important",
|
2320
|
-
color: "var(--dx-accentFocusIndicator)"
|
2321
|
-
},
|
2322
|
-
".cm-panel button": {
|
2323
|
-
"&:hover": {
|
2324
|
-
backgroundColor: "var(--dx-accentSurfaceHover) !important"
|
2325
|
-
},
|
2326
|
-
"&:active": {
|
2327
|
-
backgroundColor: "var(--dx-accentSurfaceHover)"
|
2524
|
+
var selectionOverlapsComment = (state) => {
|
2525
|
+
const commentState = state.field(commentsState, false);
|
2526
|
+
if (commentState === void 0) {
|
2527
|
+
return false;
|
2528
|
+
}
|
2529
|
+
const { selection } = state;
|
2530
|
+
for (const range of selection.ranges) {
|
2531
|
+
if (commentState.comments.some(({ range: commentRange }) => overlap(commentRange, range))) {
|
2532
|
+
return true;
|
2533
|
+
}
|
2534
|
+
}
|
2535
|
+
return false;
|
2536
|
+
};
|
2537
|
+
var hasActiveSelection = (state) => {
|
2538
|
+
return state.selection.ranges.some((range) => !range.empty);
|
2539
|
+
};
|
2540
|
+
var ExternalCommentSync = class {
|
2541
|
+
constructor(view, id, subscribe, getComments) {
|
2542
|
+
this.destroy = () => {
|
2543
|
+
this.unsubscribe();
|
2544
|
+
};
|
2545
|
+
const updateComments = () => {
|
2546
|
+
const comments2 = getComments();
|
2547
|
+
if (id === view.state.facet(documentId)) {
|
2548
|
+
queueMicrotask(() => view.dispatch({
|
2549
|
+
effects: setComments.of({
|
2550
|
+
id,
|
2551
|
+
comments: comments2
|
2552
|
+
})
|
2553
|
+
}));
|
2554
|
+
}
|
2555
|
+
};
|
2556
|
+
this.unsubscribe = subscribe(updateComments);
|
2557
|
+
}
|
2558
|
+
};
|
2559
|
+
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin4.fromClass(class {
|
2560
|
+
constructor(view) {
|
2561
|
+
return new ExternalCommentSync(view, id, subscribe, getComments);
|
2562
|
+
}
|
2563
|
+
});
|
2564
|
+
var useCommentState = (state) => {
|
2565
|
+
return useMemo2(() => EditorView9.updateListener.of((update2) => {
|
2566
|
+
if (update2.docChanged || update2.selectionSet) {
|
2567
|
+
state.comment = selectionOverlapsComment(update2.state);
|
2568
|
+
state.selection = hasActiveSelection(update2.state);
|
2569
|
+
}
|
2570
|
+
}), [
|
2571
|
+
state
|
2572
|
+
]);
|
2573
|
+
};
|
2574
|
+
var useComments = (view, id, comments2) => {
|
2575
|
+
useEffect(() => {
|
2576
|
+
if (view) {
|
2577
|
+
if (id === view.state.facet(documentId)) {
|
2578
|
+
view.dispatch({
|
2579
|
+
effects: setComments.of({
|
2580
|
+
id,
|
2581
|
+
comments: comments2 ?? []
|
2582
|
+
})
|
2583
|
+
});
|
2584
|
+
}
|
2328
2585
|
}
|
2586
|
+
});
|
2587
|
+
};
|
2588
|
+
var useCommentClickListener = (onCommentClick) => {
|
2589
|
+
return useMemo2(() => EditorView9.updateListener.of((update2) => {
|
2590
|
+
update2.transactions.forEach((transaction) => {
|
2591
|
+
transaction.effects.forEach((effect) => {
|
2592
|
+
if (effect.is(commentClickedEffect)) {
|
2593
|
+
onCommentClick(effect.value);
|
2594
|
+
}
|
2595
|
+
});
|
2596
|
+
});
|
2597
|
+
}), [
|
2598
|
+
onCommentClick
|
2599
|
+
]);
|
2600
|
+
};
|
2601
|
+
|
2602
|
+
// packages/ui/react-ui-editor/src/extensions/debug.ts
|
2603
|
+
import { syntaxTree } from "@codemirror/language";
|
2604
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
2605
|
+
var debugNodeLogger = (log8 = console.log) => {
|
2606
|
+
const logTokens = (state) => syntaxTree(state).iterate({
|
2607
|
+
enter: (node) => log8(node.type)
|
2608
|
+
});
|
2609
|
+
return StateField5.define({
|
2610
|
+
create: (state) => logTokens(state),
|
2611
|
+
update: (_, tr) => logTokens(tr.state)
|
2612
|
+
});
|
2613
|
+
};
|
2614
|
+
|
2615
|
+
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
2616
|
+
import { dropCursor, EditorView as EditorView10 } from "@codemirror/view";
|
2617
|
+
var styles4 = EditorView10.theme({
|
2618
|
+
".cm-dropCursor": {
|
2619
|
+
borderLeft: "2px solid var(--dx-accentText)",
|
2620
|
+
color: "var(--dx-accentText)",
|
2621
|
+
padding: "0 4px"
|
2329
2622
|
},
|
2330
|
-
".cm-
|
2331
|
-
|
2332
|
-
borderTop: "1px solid var(--dx-separator)"
|
2623
|
+
".cm-dropCursor:after": {
|
2624
|
+
content: '"\u2190"'
|
2333
2625
|
}
|
2626
|
+
});
|
2627
|
+
var dropFile = (options = {}) => {
|
2628
|
+
return [
|
2629
|
+
styles4,
|
2630
|
+
dropCursor(),
|
2631
|
+
EditorView10.domEventHandlers({
|
2632
|
+
drop: (event, view) => {
|
2633
|
+
event.preventDefault();
|
2634
|
+
const files = event.dataTransfer?.files;
|
2635
|
+
const pos = view.posAtCoords(event);
|
2636
|
+
if (files?.length && pos !== null) {
|
2637
|
+
view.dispatch({
|
2638
|
+
selection: {
|
2639
|
+
anchor: pos
|
2640
|
+
}
|
2641
|
+
});
|
2642
|
+
options.onDrop?.(view, {
|
2643
|
+
files
|
2644
|
+
});
|
2645
|
+
}
|
2646
|
+
}
|
2647
|
+
})
|
2648
|
+
];
|
2334
2649
|
};
|
2335
2650
|
|
2651
|
+
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2652
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
2653
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
2654
|
+
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
2655
|
+
import { searchKeymap } from "@codemirror/search";
|
2656
|
+
import { EditorState } from "@codemirror/state";
|
2657
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
2658
|
+
import { EditorView as EditorView12, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap6, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
2659
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
2660
|
+
import merge from "lodash.merge";
|
2661
|
+
import { generateName } from "@dxos/display-name";
|
2662
|
+
import { log as log5 } from "@dxos/log";
|
2663
|
+
import { hueTokens } from "@dxos/react-ui-theme";
|
2664
|
+
import { hexToHue, isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
2665
|
+
|
2666
|
+
// packages/ui/react-ui-editor/src/extensions/focus.ts
|
2667
|
+
import { StateEffect as StateEffect4, StateField as StateField6 } from "@codemirror/state";
|
2668
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
2669
|
+
var focusEffect = StateEffect4.define();
|
2670
|
+
var focusField = StateField6.define({
|
2671
|
+
create: () => false,
|
2672
|
+
update: (value, tr) => {
|
2673
|
+
for (const effect of tr.effects) {
|
2674
|
+
if (effect.is(focusEffect)) {
|
2675
|
+
return effect.value;
|
2676
|
+
}
|
2677
|
+
}
|
2678
|
+
return value;
|
2679
|
+
}
|
2680
|
+
});
|
2681
|
+
var focus = [
|
2682
|
+
focusField,
|
2683
|
+
EditorView11.domEventHandlers({
|
2684
|
+
focus: (event, view) => {
|
2685
|
+
setTimeout(() => view.dispatch({
|
2686
|
+
effects: focusEffect.of(true)
|
2687
|
+
}));
|
2688
|
+
},
|
2689
|
+
blur: (event, view) => {
|
2690
|
+
setTimeout(() => view.dispatch({
|
2691
|
+
effects: focusEffect.of(false)
|
2692
|
+
}));
|
2693
|
+
}
|
2694
|
+
})
|
2695
|
+
];
|
2696
|
+
|
2336
2697
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
2337
2698
|
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
2338
2699
|
var preventNewline = EditorState.transactionFilter.of((tr) => tr.newDoc.lines > 1 ? [] : tr);
|
@@ -2358,7 +2719,7 @@ var createBasicExtensions = (_props) => {
|
|
2358
2719
|
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
2359
2720
|
return [
|
2360
2721
|
// NOTE: Doesn't catch errors in keymap functions.
|
2361
|
-
|
2722
|
+
EditorView12.exceptionSink.of((err) => {
|
2362
2723
|
log5.catch(err, void 0, {
|
2363
2724
|
F: __dxlog_file8,
|
2364
2725
|
L: 96,
|
@@ -2377,11 +2738,11 @@ var createBasicExtensions = (_props) => {
|
|
2377
2738
|
props.highlightActiveLine && highlightActiveLine(),
|
2378
2739
|
props.history && history(),
|
2379
2740
|
props.lineNumbers && lineNumbers(),
|
2380
|
-
props.lineWrapping &&
|
2741
|
+
props.lineWrapping && EditorView12.lineWrapping,
|
2381
2742
|
props.placeholder && placeholder(props.placeholder),
|
2382
2743
|
props.readonly && [
|
2383
2744
|
EditorState.readOnly.of(true),
|
2384
|
-
|
2745
|
+
EditorView12.editable.of(false)
|
2385
2746
|
],
|
2386
2747
|
props.scrollPastEnd && scrollPastEnd(),
|
2387
2748
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
@@ -2410,14 +2771,14 @@ var defaultThemeSlots = {
|
|
2410
2771
|
var createThemeExtensions = ({ themeMode, styles: styles5, syntaxHighlighting: _syntaxHighlighting, slots: _slots } = {}) => {
|
2411
2772
|
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
2412
2773
|
return [
|
2413
|
-
|
2414
|
-
|
2774
|
+
EditorView12.darkTheme.of(themeMode === "dark"),
|
2775
|
+
EditorView12.baseTheme(styles5 ? merge({}, defaultTheme, styles5) : defaultTheme),
|
2415
2776
|
// https://github.com/codemirror/theme-one-dark
|
2416
2777
|
_syntaxHighlighting && (themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)),
|
2417
|
-
slots.editor?.className &&
|
2778
|
+
slots.editor?.className && EditorView12.editorAttributes.of({
|
2418
2779
|
class: slots.editor.className
|
2419
2780
|
}),
|
2420
|
-
slots.content?.className &&
|
2781
|
+
slots.content?.className && EditorView12.contentAttributes.of({
|
2421
2782
|
class: slots.content.className
|
2422
2783
|
})
|
2423
2784
|
].filter(isNotFalsy3);
|
@@ -2446,8 +2807,8 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2446
2807
|
|
2447
2808
|
// packages/ui/react-ui-editor/src/extensions/folding.tsx
|
2448
2809
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
2449
|
-
import { EditorView as
|
2450
|
-
import
|
2810
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
2811
|
+
import React3 from "react";
|
2451
2812
|
import { Icon } from "@dxos/react-ui";
|
2452
2813
|
var folding = (_props = {}) => [
|
2453
2814
|
codeFolding({
|
@@ -2460,7 +2821,7 @@ var folding = (_props = {}) => [
|
|
2460
2821
|
const el = createElement("div", {
|
2461
2822
|
className: "flex h-full items-center"
|
2462
2823
|
});
|
2463
|
-
return renderRoot(el, /* @__PURE__ */
|
2824
|
+
return renderRoot(el, /* @__PURE__ */ React3.createElement(Icon, {
|
2464
2825
|
icon: "ph--caret-right--regular",
|
2465
2826
|
size: 3,
|
2466
2827
|
classNames: [
|
@@ -2470,7 +2831,7 @@ var folding = (_props = {}) => [
|
|
2470
2831
|
}));
|
2471
2832
|
}
|
2472
2833
|
}),
|
2473
|
-
|
2834
|
+
EditorView13.theme({
|
2474
2835
|
".cm-foldGutter": {
|
2475
2836
|
opacity: 0.3,
|
2476
2837
|
transition: "opacity 0.3s",
|
@@ -2483,14 +2844,14 @@ var folding = (_props = {}) => [
|
|
2483
2844
|
];
|
2484
2845
|
|
2485
2846
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
2486
|
-
import { EditorView as
|
2847
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
2487
2848
|
var listener = ({ onFocus, onChange }) => {
|
2488
2849
|
const extensions = [];
|
2489
|
-
onFocus && extensions.push(
|
2850
|
+
onFocus && extensions.push(EditorView14.focusChangeEffect.of((_, focusing) => {
|
2490
2851
|
onFocus(focusing);
|
2491
2852
|
return null;
|
2492
2853
|
}));
|
2493
|
-
onChange && extensions.push(
|
2854
|
+
onChange && extensions.push(EditorView14.updateListener.of((update2) => {
|
2494
2855
|
onChange(update2.state.doc.toString(), update2.state.facet(documentId));
|
2495
2856
|
}));
|
2496
2857
|
return extensions;
|
@@ -2500,8 +2861,8 @@ var listener = ({ onFocus, onChange }) => {
|
|
2500
2861
|
import { snippet } from "@codemirror/autocomplete";
|
2501
2862
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
2502
2863
|
import { EditorSelection } from "@codemirror/state";
|
2503
|
-
import { EditorView as
|
2504
|
-
import { useMemo as
|
2864
|
+
import { EditorView as EditorView15, keymap as keymap7 } from "@codemirror/view";
|
2865
|
+
import { useMemo as useMemo3 } from "react";
|
2505
2866
|
var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
2506
2867
|
var Inline;
|
2507
2868
|
(function(Inline2) {
|
@@ -3588,65 +3949,56 @@ var getFormatting = (state) => {
|
|
3588
3949
|
listStyle: listStyle || null
|
3589
3950
|
};
|
3590
3951
|
};
|
3591
|
-
var useFormattingState = () => {
|
3592
|
-
|
3593
|
-
const observer = useMemo2(() => EditorView14.updateListener.of((update2) => {
|
3952
|
+
var useFormattingState = (state) => {
|
3953
|
+
return useMemo3(() => EditorView15.updateListener.of((update2) => {
|
3594
3954
|
if (update2.docChanged || update2.selectionSet) {
|
3595
|
-
|
3596
|
-
|
3597
|
-
if (!prevState || !formattingEquals(prevState, newState)) {
|
3598
|
-
return newState;
|
3599
|
-
}
|
3600
|
-
return prevState;
|
3955
|
+
Object.entries(getFormatting(update2.state)).forEach(([key, active]) => {
|
3956
|
+
state[key] = active;
|
3601
3957
|
});
|
3602
3958
|
}
|
3603
3959
|
}), []);
|
3604
|
-
return [
|
3605
|
-
state,
|
3606
|
-
observer
|
3607
|
-
];
|
3608
3960
|
};
|
3609
3961
|
|
3610
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
3611
|
-
var
|
3962
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/editorAction.ts
|
3963
|
+
var processEditorPayload = (view, { type, data }) => {
|
3612
3964
|
let inlineType, listType;
|
3613
|
-
switch (
|
3965
|
+
switch (type) {
|
3614
3966
|
case "heading":
|
3615
|
-
setHeading(parseInt(
|
3967
|
+
setHeading(parseInt(data))(view);
|
3616
3968
|
break;
|
3617
3969
|
case "strong":
|
3618
3970
|
case "emphasis":
|
3619
3971
|
case "strikethrough":
|
3620
3972
|
case "code":
|
3621
|
-
inlineType =
|
3622
|
-
(typeof
|
3973
|
+
inlineType = type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
3974
|
+
(typeof data === "boolean" ? setStyle(inlineType, data) : toggleStyle(inlineType))(view);
|
3623
3975
|
break;
|
3624
3976
|
case "list-ordered":
|
3625
3977
|
case "list-bullet":
|
3626
3978
|
case "list-task":
|
3627
|
-
listType =
|
3628
|
-
(
|
3979
|
+
listType = type === "list-ordered" ? List.Ordered : type === "list-bullet" ? List.Bullet : List.Task;
|
3980
|
+
(data === false ? removeList(listType) : data === true ? addList(listType) : toggleList(listType))(view);
|
3629
3981
|
break;
|
3630
3982
|
case "blockquote":
|
3631
|
-
(
|
3983
|
+
(data === false ? removeBlockquote : data === true ? addBlockquote : toggleBlockquote)(view);
|
3632
3984
|
break;
|
3633
3985
|
case "codeblock":
|
3634
|
-
(
|
3986
|
+
(data === false ? removeCodeblock : addCodeblock)(view);
|
3635
3987
|
break;
|
3636
3988
|
case "table":
|
3637
3989
|
insertTable(view);
|
3638
3990
|
break;
|
3639
3991
|
case "link":
|
3640
|
-
(
|
3992
|
+
(data === false ? removeLink : addLink())(view);
|
3641
3993
|
break;
|
3642
3994
|
case "image":
|
3643
3995
|
addLink({
|
3644
|
-
url:
|
3996
|
+
url: data,
|
3645
3997
|
image: true
|
3646
3998
|
})(view);
|
3647
3999
|
break;
|
3648
4000
|
case "comment":
|
3649
|
-
|
4001
|
+
createComment2(view);
|
3650
4002
|
break;
|
3651
4003
|
}
|
3652
4004
|
requestAnimationFrame(() => {
|
@@ -3910,9 +4262,9 @@ var convertTreeToJson = (state) => {
|
|
3910
4262
|
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
3911
4263
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
3912
4264
|
import { RangeSetBuilder as RangeSetBuilder3, StateEffect as StateEffect5 } from "@codemirror/state";
|
3913
|
-
import { EditorView as
|
4265
|
+
import { EditorView as EditorView19, Decoration as Decoration7, WidgetType as WidgetType5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
3914
4266
|
import { invariant as invariant4 } from "@dxos/invariant";
|
3915
|
-
import { mx as
|
4267
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
3916
4268
|
|
3917
4269
|
// packages/ui/react-ui-editor/src/extensions/markdown/changes.ts
|
3918
4270
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
@@ -4061,7 +4413,7 @@ var getValidUrl = (str) => {
|
|
4061
4413
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
4062
4414
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
4063
4415
|
import { StateField as StateField8 } from "@codemirror/state";
|
4064
|
-
import { Decoration as Decoration5, EditorView as
|
4416
|
+
import { Decoration as Decoration5, EditorView as EditorView16, WidgetType as WidgetType3 } from "@codemirror/view";
|
4065
4417
|
var image = (_options = {}) => {
|
4066
4418
|
return [
|
4067
4419
|
StateField8.define({
|
@@ -4089,7 +4441,7 @@ var image = (_options = {}) => {
|
|
4089
4441
|
add: buildDecorations(from, to, tr.state)
|
4090
4442
|
});
|
4091
4443
|
},
|
4092
|
-
provide: (field) =>
|
4444
|
+
provide: (field) => EditorView16.decorations.from(field)
|
4093
4445
|
})
|
4094
4446
|
];
|
4095
4447
|
};
|
@@ -4149,10 +4501,10 @@ var ImageWidget = class extends WidgetType3 {
|
|
4149
4501
|
};
|
4150
4502
|
|
4151
4503
|
// packages/ui/react-ui-editor/src/extensions/markdown/styles.ts
|
4152
|
-
import { EditorView as
|
4504
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
4153
4505
|
var bulletListIndentationWidth = 24;
|
4154
4506
|
var orderedListIndentationWidth = 36;
|
4155
|
-
var formattingStyles =
|
4507
|
+
var formattingStyles = EditorView17.theme({
|
4156
4508
|
/**
|
4157
4509
|
* Horizontal rule.
|
4158
4510
|
*/
|
@@ -4246,18 +4598,39 @@ var formattingStyles = EditorView16.theme({
|
|
4246
4598
|
height: "auto",
|
4247
4599
|
borderTop: "0.5rem solid transparent",
|
4248
4600
|
borderBottom: "0.5rem solid transparent"
|
4601
|
+
},
|
4602
|
+
".cm-image-with-loader": {
|
4603
|
+
display: "block",
|
4604
|
+
opacity: "0",
|
4605
|
+
transitionDuration: "350ms",
|
4606
|
+
transitionProperty: "opacity"
|
4607
|
+
},
|
4608
|
+
".cm-image-with-loader.cm-loaded-image": {
|
4609
|
+
opacity: "1"
|
4610
|
+
},
|
4611
|
+
".cm-image-wrapper": {
|
4612
|
+
"grid-template-columns": "1fr",
|
4613
|
+
display: "grid",
|
4614
|
+
margin: "0.5rem 0",
|
4615
|
+
overflow: "hidden",
|
4616
|
+
transitionDuration: "350ms",
|
4617
|
+
transitionProperty: "height",
|
4618
|
+
"& > *": {
|
4619
|
+
"grid-row-start": 1,
|
4620
|
+
"grid-column-start": 1
|
4621
|
+
}
|
4249
4622
|
}
|
4250
4623
|
});
|
4251
4624
|
|
4252
4625
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
4253
4626
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
4254
4627
|
import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField9 } from "@codemirror/state";
|
4255
|
-
import { Decoration as Decoration6, EditorView as
|
4628
|
+
import { Decoration as Decoration6, EditorView as EditorView18, WidgetType as WidgetType4 } from "@codemirror/view";
|
4256
4629
|
var table = (options = {}) => {
|
4257
4630
|
return StateField9.define({
|
4258
4631
|
create: (state) => update(state, options),
|
4259
4632
|
update: (_, tr) => update(tr.state, options),
|
4260
|
-
provide: (field) =>
|
4633
|
+
provide: (field) => EditorView18.decorations.from(field)
|
4261
4634
|
});
|
4262
4635
|
};
|
4263
4636
|
var update = (state, _options) => {
|
@@ -4441,16 +4814,16 @@ var TextWidget = class extends WidgetType5 {
|
|
4441
4814
|
};
|
4442
4815
|
var hide = Decoration7.replace({});
|
4443
4816
|
var blockQuote = Decoration7.line({
|
4444
|
-
class:
|
4817
|
+
class: mx4("cm-blockquote")
|
4445
4818
|
});
|
4446
4819
|
var fencedCodeLine = Decoration7.line({
|
4447
|
-
class:
|
4820
|
+
class: mx4("cm-code cm-codeblock-line")
|
4448
4821
|
});
|
4449
4822
|
var fencedCodeLineFirst = Decoration7.line({
|
4450
|
-
class:
|
4823
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-first")
|
4451
4824
|
});
|
4452
4825
|
var fencedCodeLineLast = Decoration7.line({
|
4453
|
-
class:
|
4826
|
+
class: mx4("cm-code cm-codeblock-line", "cm-codeblock-last")
|
4454
4827
|
});
|
4455
4828
|
var commentBlockLine = fencedCodeLine;
|
4456
4829
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
@@ -4791,9 +5164,9 @@ var decorateMarkdown = (options = {}) => {
|
|
4791
5164
|
}
|
4792
5165
|
}, {
|
4793
5166
|
provide: (plugin) => [
|
4794
|
-
|
4795
|
-
|
4796
|
-
|
5167
|
+
EditorView19.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5168
|
+
EditorView19.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration7.none),
|
5169
|
+
EditorView19.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration7.none)
|
4797
5170
|
]
|
4798
5171
|
}),
|
4799
5172
|
image(),
|
@@ -4980,428 +5353,29 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
4980
5353
|
];
|
4981
5354
|
};
|
4982
5355
|
|
4983
|
-
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
4984
|
-
var iconStyles = getSize(5);
|
4985
|
-
var buttonStyles = "min-bs-0 p-1";
|
4986
|
-
var tooltipProps = {
|
4987
|
-
side: "top",
|
4988
|
-
classNames: "z-10"
|
4989
|
-
};
|
4990
|
-
var ToolbarSeparator = () => /* @__PURE__ */ React3.createElement("div", {
|
4991
|
-
role: "separator",
|
4992
|
-
className: "grow"
|
4993
|
-
});
|
4994
|
-
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
4995
|
-
var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
4996
|
-
return /* @__PURE__ */ React3.createElement(ToolbarContextProvider, {
|
4997
|
-
onAction,
|
4998
|
-
state
|
4999
|
-
}, /* @__PURE__ */ React3.createElement(ElevationProvider, {
|
5000
|
-
elevation: "positioned"
|
5001
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Root, {
|
5002
|
-
classNames: [
|
5003
|
-
"p-1 is-full shrink-0 overflow-x-auto overflow-y-hidden",
|
5004
|
-
classNames
|
5005
|
-
],
|
5006
|
-
style: {
|
5007
|
-
contain: "layout"
|
5008
|
-
}
|
5009
|
-
}, children)));
|
5010
|
-
};
|
5011
|
-
var ToolbarToggleButton = ({ Icon: Icon2, children, ...props }) => {
|
5012
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5013
|
-
asChild: true
|
5014
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroupItem, {
|
5015
|
-
variant: "ghost",
|
5016
|
-
...props,
|
5017
|
-
classNames: buttonStyles
|
5018
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5019
|
-
className: iconStyles
|
5020
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5021
|
-
className: "sr-only"
|
5022
|
-
}, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5023
|
-
};
|
5024
|
-
var ToolbarButton = ({ Icon: Icon2, children, ...props }) => {
|
5025
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5026
|
-
asChild: true
|
5027
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5028
|
-
variant: "ghost",
|
5029
|
-
...props,
|
5030
|
-
classNames: buttonStyles
|
5031
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5032
|
-
className: iconStyles
|
5033
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5034
|
-
className: "sr-only"
|
5035
|
-
}, children))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5036
|
-
};
|
5037
|
-
var HeadingIcons = {
|
5038
|
-
"0": Paragraph,
|
5039
|
-
"1": TextHOne,
|
5040
|
-
"2": TextHTwo,
|
5041
|
-
"3": TextHThree,
|
5042
|
-
"4": TextHFour,
|
5043
|
-
"5": TextHFive,
|
5044
|
-
"6": TextHSix
|
5045
|
-
};
|
5046
|
-
var MarkdownHeading = () => {
|
5047
|
-
const { t } = useTranslation(translationKey);
|
5048
|
-
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
5049
|
-
const blockType = state ? state.blockType : "paragraph";
|
5050
|
-
const header = blockType && /heading(\d)/.exec(blockType);
|
5051
|
-
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
5052
|
-
const HeadingIcon = HeadingIcons[value ?? "0"];
|
5053
|
-
const suppressNextTooltip = useRef(false);
|
5054
|
-
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
5055
|
-
const [selectOpen, setSelectOpen] = useState3(false);
|
5056
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
|
5057
|
-
open: tooltipOpen,
|
5058
|
-
onOpenChange: (nextOpen) => {
|
5059
|
-
if (nextOpen && suppressNextTooltip.current) {
|
5060
|
-
suppressNextTooltip.current = false;
|
5061
|
-
return setTooltipOpen(false);
|
5062
|
-
} else {
|
5063
|
-
return setTooltipOpen(nextOpen);
|
5064
|
-
}
|
5065
|
-
}
|
5066
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
5067
|
-
open: selectOpen,
|
5068
|
-
onOpenChange: (nextOpen) => {
|
5069
|
-
if (!nextOpen) {
|
5070
|
-
suppressNextTooltip.current = true;
|
5071
|
-
}
|
5072
|
-
return setSelectOpen(nextOpen);
|
5073
|
-
}
|
5074
|
-
}, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5075
|
-
asChild: true
|
5076
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5077
|
-
asChild: true
|
5078
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
5079
|
-
asChild: true
|
5080
|
-
}, /* @__PURE__ */ React3.createElement(Button, {
|
5081
|
-
variant: "ghost",
|
5082
|
-
classNames: buttonStyles,
|
5083
|
-
disabled: value === null
|
5084
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5085
|
-
className: "sr-only"
|
5086
|
-
}, t("heading label")), /* @__PURE__ */ React3.createElement(HeadingIcon, {
|
5087
|
-
className: iconStyles
|
5088
|
-
}), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
|
5089
|
-
classNames: "is-min md:is-min",
|
5090
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
5091
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, Object.keys(HeadingIcons).map((level) => {
|
5092
|
-
const Icon2 = HeadingIcons[level];
|
5093
|
-
return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
|
5094
|
-
key: level,
|
5095
|
-
checked: value === level,
|
5096
|
-
onClick: () => onAction?.({
|
5097
|
-
type: "heading",
|
5098
|
-
data: level
|
5099
|
-
})
|
5100
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5101
|
-
className: "sr-only"
|
5102
|
-
}, t("heading level label", {
|
5103
|
-
count: parseInt(level)
|
5104
|
-
})), /* @__PURE__ */ React3.createElement(Icon2, {
|
5105
|
-
className: iconStyles
|
5106
|
-
}), /* @__PURE__ */ React3.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React3.createElement(Check, null)));
|
5107
|
-
})), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5108
|
-
};
|
5109
|
-
var markdownStyles = [
|
5110
|
-
{
|
5111
|
-
type: "strong",
|
5112
|
-
Icon: TextB,
|
5113
|
-
getState: (state) => !!state?.strong
|
5114
|
-
},
|
5115
|
-
{
|
5116
|
-
type: "emphasis",
|
5117
|
-
Icon: TextItalic,
|
5118
|
-
getState: (state) => !!state?.emphasis
|
5119
|
-
},
|
5120
|
-
{
|
5121
|
-
type: "strikethrough",
|
5122
|
-
Icon: TextStrikethrough,
|
5123
|
-
getState: (state) => !!state?.strikethrough
|
5124
|
-
},
|
5125
|
-
{
|
5126
|
-
type: "code",
|
5127
|
-
Icon: Code,
|
5128
|
-
getState: (state) => !!state?.code
|
5129
|
-
},
|
5130
|
-
{
|
5131
|
-
type: "link",
|
5132
|
-
Icon: Link,
|
5133
|
-
getState: (state) => !!state?.link
|
5134
|
-
}
|
5135
|
-
];
|
5136
|
-
var MarkdownStyles = () => {
|
5137
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5138
|
-
const { t } = useTranslation(translationKey);
|
5139
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5140
|
-
type: "multiple",
|
5141
|
-
value: markdownStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)
|
5142
|
-
}, markdownStyles.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5143
|
-
key: type,
|
5144
|
-
value: type,
|
5145
|
-
Icon: Icon2,
|
5146
|
-
disabled: state?.blockType === "codeblock",
|
5147
|
-
onClick: state ? () => onAction?.({
|
5148
|
-
type,
|
5149
|
-
data: !getState(state)
|
5150
|
-
}) : void 0
|
5151
|
-
}, t(`${type} label`))));
|
5152
|
-
};
|
5153
|
-
var markdownLists = [
|
5154
|
-
{
|
5155
|
-
type: "list-bullet",
|
5156
|
-
Icon: ListBullets,
|
5157
|
-
getState: (state) => state.listStyle === "bullet"
|
5158
|
-
},
|
5159
|
-
{
|
5160
|
-
type: "list-ordered",
|
5161
|
-
Icon: ListNumbers,
|
5162
|
-
getState: (state) => state.listStyle === "ordered"
|
5163
|
-
},
|
5164
|
-
{
|
5165
|
-
type: "list-task",
|
5166
|
-
Icon: ListChecks,
|
5167
|
-
getState: (state) => state.listStyle === "task"
|
5168
|
-
}
|
5169
|
-
];
|
5170
|
-
var MarkdownLists = () => {
|
5171
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5172
|
-
const { t } = useTranslation(translationKey);
|
5173
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5174
|
-
type: "single",
|
5175
|
-
value: state?.listStyle ? `list-${state.listStyle}` : ""
|
5176
|
-
}, markdownLists.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5177
|
-
key: type,
|
5178
|
-
value: type,
|
5179
|
-
Icon: Icon2,
|
5180
|
-
onClick: state ? () => onAction?.({
|
5181
|
-
type,
|
5182
|
-
data: !getState(state)
|
5183
|
-
}) : void 0
|
5184
|
-
}, t(`${type} label`))));
|
5185
|
-
};
|
5186
|
-
var markdownBlocks = [
|
5187
|
-
{
|
5188
|
-
type: "blockquote",
|
5189
|
-
Icon: Quotes,
|
5190
|
-
getState: (state) => !!state?.blockQuote
|
5191
|
-
},
|
5192
|
-
{
|
5193
|
-
type: "codeblock",
|
5194
|
-
Icon: CodeBlock,
|
5195
|
-
getState: (state) => state.blockType === "codeblock"
|
5196
|
-
},
|
5197
|
-
{
|
5198
|
-
type: "table",
|
5199
|
-
Icon: Table2,
|
5200
|
-
getState: (state) => state.blockType === "tablecell",
|
5201
|
-
disabled: (state) => !state.blankLine
|
5202
|
-
}
|
5203
|
-
];
|
5204
|
-
var MarkdownBlocks = () => {
|
5205
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
5206
|
-
const { t } = useTranslation(translationKey);
|
5207
|
-
const value = markdownBlocks.find(({ getState }) => state && getState(state));
|
5208
|
-
return /* @__PURE__ */ React3.createElement(NaturalToolbar.ToggleGroup, {
|
5209
|
-
type: "single",
|
5210
|
-
value: value?.type ?? ""
|
5211
|
-
}, markdownBlocks.map(({ type, disabled, getState, Icon: Icon2 }) => /* @__PURE__ */ React3.createElement(ToolbarToggleButton, {
|
5212
|
-
key: type,
|
5213
|
-
value: type,
|
5214
|
-
Icon: Icon2,
|
5215
|
-
disabled: !state || disabled?.(state),
|
5216
|
-
onClick: state ? () => onAction?.({
|
5217
|
-
type,
|
5218
|
-
data: !getState(state)
|
5219
|
-
}) : void 0
|
5220
|
-
}, t(`${type} label`))));
|
5221
|
-
};
|
5222
|
-
var MarkdownStandard = () => /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(MarkdownHeading, null), /* @__PURE__ */ React3.createElement(MarkdownStyles, null), /* @__PURE__ */ React3.createElement(MarkdownLists, null), /* @__PURE__ */ React3.createElement(MarkdownBlocks, null));
|
5223
|
-
var MarkdownCustom = ({ onUpload } = {}) => {
|
5224
|
-
const { onAction } = useToolbarContext("MarkdownStyles");
|
5225
|
-
const { t } = useTranslation(translationKey);
|
5226
|
-
const { acceptedFiles, getInputProps, open } = useDropzone({
|
5227
|
-
multiple: false,
|
5228
|
-
noDrag: true,
|
5229
|
-
accept: {
|
5230
|
-
"image/*": [
|
5231
|
-
".jpg",
|
5232
|
-
".jpeg",
|
5233
|
-
".png",
|
5234
|
-
".gif"
|
5235
|
-
]
|
5236
|
-
}
|
5237
|
-
});
|
5238
|
-
useEffect2(() => {
|
5239
|
-
if (onUpload && acceptedFiles.length) {
|
5240
|
-
requestAnimationFrame(async () => {
|
5241
|
-
const f = acceptedFiles[0];
|
5242
|
-
const file = new File([
|
5243
|
-
f
|
5244
|
-
], f.name, {
|
5245
|
-
type: f.type,
|
5246
|
-
lastModified: f.lastModified
|
5247
|
-
});
|
5248
|
-
const info = await onUpload(file);
|
5249
|
-
if (info) {
|
5250
|
-
onAction?.({
|
5251
|
-
type: "image",
|
5252
|
-
data: info.url
|
5253
|
-
});
|
5254
|
-
}
|
5255
|
-
});
|
5256
|
-
}
|
5257
|
-
}, [
|
5258
|
-
acceptedFiles
|
5259
|
-
]);
|
5260
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("input", getInputProps()), /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5261
|
-
value: "image",
|
5262
|
-
Icon: Image,
|
5263
|
-
onClick: () => open()
|
5264
|
-
}, t("image label")));
|
5265
|
-
};
|
5266
|
-
var ViewModeIcons = {
|
5267
|
-
preview: PencilSimple,
|
5268
|
-
readonly: PencilSimpleSlash,
|
5269
|
-
source: MarkdownLogo
|
5270
|
-
};
|
5271
|
-
var MarkdownView = ({ mode }) => {
|
5272
|
-
const { t } = useTranslation(translationKey);
|
5273
|
-
const { onAction } = useToolbarContext("ViewMode");
|
5274
|
-
const ModeIcon = ViewModeIcons[mode ?? "preview"];
|
5275
|
-
const suppressNextTooltip = useRef(false);
|
5276
|
-
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
5277
|
-
const [selectOpen, setSelectOpen] = useState3(false);
|
5278
|
-
return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
|
5279
|
-
open: tooltipOpen,
|
5280
|
-
onOpenChange: (nextOpen) => {
|
5281
|
-
if (nextOpen && suppressNextTooltip.current) {
|
5282
|
-
suppressNextTooltip.current = false;
|
5283
|
-
return setTooltipOpen(false);
|
5284
|
-
} else {
|
5285
|
-
return setTooltipOpen(nextOpen);
|
5286
|
-
}
|
5287
|
-
}
|
5288
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
|
5289
|
-
open: selectOpen,
|
5290
|
-
onOpenChange: (nextOpen) => {
|
5291
|
-
if (!nextOpen) {
|
5292
|
-
suppressNextTooltip.current = true;
|
5293
|
-
}
|
5294
|
-
return setSelectOpen(nextOpen);
|
5295
|
-
}
|
5296
|
-
}, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
|
5297
|
-
asChild: true
|
5298
|
-
}, /* @__PURE__ */ React3.createElement(NaturalToolbar.Button, {
|
5299
|
-
asChild: true
|
5300
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
|
5301
|
-
asChild: true
|
5302
|
-
}, /* @__PURE__ */ React3.createElement(Button, {
|
5303
|
-
variant: "ghost",
|
5304
|
-
classNames: buttonStyles
|
5305
|
-
}, /* @__PURE__ */ React3.createElement("span", {
|
5306
|
-
className: "sr-only"
|
5307
|
-
}, t("mode label")), /* @__PURE__ */ React3.createElement(ModeIcon, {
|
5308
|
-
className: iconStyles
|
5309
|
-
}), /* @__PURE__ */ React3.createElement(CaretDown, null))))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
|
5310
|
-
classNames: "is-min md:is-min",
|
5311
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
5312
|
-
}, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, EditorViewModes.map((value) => {
|
5313
|
-
const Icon2 = ViewModeIcons[value];
|
5314
|
-
return /* @__PURE__ */ React3.createElement(DropdownMenu.CheckboxItem, {
|
5315
|
-
key: value,
|
5316
|
-
checked: value === mode,
|
5317
|
-
onClick: () => onAction?.({
|
5318
|
-
type: "view-mode",
|
5319
|
-
data: value
|
5320
|
-
})
|
5321
|
-
}, /* @__PURE__ */ React3.createElement(Icon2, {
|
5322
|
-
className: iconStyles
|
5323
|
-
}), /* @__PURE__ */ React3.createElement("span", {
|
5324
|
-
className: "whitespace-nowrap grow"
|
5325
|
-
}, t(`${value} mode label`)), /* @__PURE__ */ React3.createElement(Check, {
|
5326
|
-
className: value === mode ? "visible" : "invisible"
|
5327
|
-
}));
|
5328
|
-
})), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, tooltipProps, t("view mode label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))));
|
5329
|
-
};
|
5330
|
-
var MarkdownActions = () => {
|
5331
|
-
const { onAction, state } = useToolbarContext("MarkdownActions");
|
5332
|
-
const { t } = useTranslation(translationKey);
|
5333
|
-
let commentToolTipKey = "comment label";
|
5334
|
-
if (state?.comment) {
|
5335
|
-
commentToolTipKey = "selection overlaps existing comment label";
|
5336
|
-
} else if (state?.selection === false) {
|
5337
|
-
commentToolTipKey = "select text to comment label";
|
5338
|
-
}
|
5339
|
-
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5340
|
-
value: "search",
|
5341
|
-
Icon: MagnifyingGlass,
|
5342
|
-
onClick: () => onAction?.({
|
5343
|
-
type: "search"
|
5344
|
-
})
|
5345
|
-
}, t("search label")), /* @__PURE__ */ React3.createElement(ToolbarButton, {
|
5346
|
-
value: "comment",
|
5347
|
-
Icon: ChatText,
|
5348
|
-
"data-testid": "editor.toolbar.comment",
|
5349
|
-
onClick: () => onAction?.({
|
5350
|
-
type: "comment"
|
5351
|
-
}),
|
5352
|
-
disabled: !state || state.comment || !state.selection
|
5353
|
-
}, t(commentToolTipKey)));
|
5354
|
-
};
|
5355
|
-
var Toolbar = {
|
5356
|
-
Root: ToolbarRoot,
|
5357
|
-
Button: ToolbarToggleButton,
|
5358
|
-
Separator: ToolbarSeparator,
|
5359
|
-
View: MarkdownView,
|
5360
|
-
Markdown: MarkdownStandard,
|
5361
|
-
Custom: MarkdownCustom,
|
5362
|
-
Actions: MarkdownActions
|
5363
|
-
};
|
5364
|
-
|
5365
|
-
// packages/ui/react-ui-editor/src/defaults.ts
|
5366
|
-
import { EditorView as EditorView19 } from "@codemirror/view";
|
5367
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
5368
|
-
var margin = "!mt-[1rem]";
|
5369
|
-
var editorContent = mx3(margin, "!mli-auto w-full max-w-[min(50rem,100%-2rem)]");
|
5370
|
-
var editorFullWidth = mx3(margin);
|
5371
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
5372
|
-
var editorGutter = EditorView19.theme({
|
5373
|
-
// Match margin from content.
|
5374
|
-
".cm-gutters": {
|
5375
|
-
marginTop: "16px",
|
5376
|
-
paddingRight: "1rem"
|
5377
|
-
}
|
5378
|
-
});
|
5379
|
-
var editorMonospace = EditorView19.theme({
|
5380
|
-
".cm-content": {
|
5381
|
-
fontFamily: fontMono
|
5382
|
-
}
|
5383
|
-
});
|
5384
|
-
|
5385
5356
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
5357
|
+
import { useCallback as useCallback2 } from "react";
|
5386
5358
|
var useActionHandler = (view) => {
|
5387
|
-
return (action) => view &&
|
5359
|
+
return useCallback2((action) => view && processEditorPayload(view, action.properties), [
|
5360
|
+
view
|
5361
|
+
]);
|
5388
5362
|
};
|
5389
5363
|
|
5390
5364
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
5391
5365
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
5392
5366
|
import { EditorView as EditorView20 } from "@codemirror/view";
|
5393
5367
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
5394
|
-
import { useCallback, useEffect as
|
5368
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo4, useRef, useState } from "react";
|
5395
5369
|
import { log as log7 } from "@dxos/log";
|
5396
5370
|
import { getProviderValue, isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
5397
5371
|
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
5398
5372
|
var instanceCount = 0;
|
5399
5373
|
var useTextEditor = (props = {}, deps = []) => {
|
5400
|
-
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } =
|
5401
|
-
const [instanceId] =
|
5402
|
-
const [view, setView] =
|
5403
|
-
const parentRef =
|
5404
|
-
|
5374
|
+
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } = useMemo4(() => getProviderValue(props), deps ?? []);
|
5375
|
+
const [instanceId] = useState(() => `text-editor-${++instanceCount}`);
|
5376
|
+
const [view, setView] = useState();
|
5377
|
+
const parentRef = useRef(null);
|
5378
|
+
useEffect2(() => {
|
5405
5379
|
let view2;
|
5406
5380
|
if (parentRef.current) {
|
5407
5381
|
log7("create", {
|
@@ -5475,7 +5449,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5475
5449
|
view2?.destroy();
|
5476
5450
|
};
|
5477
5451
|
}, deps);
|
5478
|
-
|
5452
|
+
useEffect2(() => {
|
5479
5453
|
if (view) {
|
5480
5454
|
if (scrollTo || selection) {
|
5481
5455
|
if (selection && selection.anchor > view.state.doc.length) {
|
@@ -5502,7 +5476,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5502
5476
|
scrollTo,
|
5503
5477
|
selection
|
5504
5478
|
]);
|
5505
|
-
|
5479
|
+
useEffect2(() => {
|
5506
5480
|
if (view && autoFocus) {
|
5507
5481
|
view.focus();
|
5508
5482
|
}
|
@@ -5516,7 +5490,7 @@ var useTextEditor = (props = {}, deps = []) => {
|
|
5516
5490
|
Escape: view?.state.facet(editorInputMode).noTabster
|
5517
5491
|
}
|
5518
5492
|
});
|
5519
|
-
const handleKeyUp =
|
5493
|
+
const handleKeyUp = useCallback3((event) => {
|
5520
5494
|
const { key, target, currentTarget } = event;
|
5521
5495
|
if (target === currentTarget) {
|
5522
5496
|
switch (key) {
|
@@ -5545,6 +5519,7 @@ export {
|
|
5545
5519
|
EditorInputMode,
|
5546
5520
|
EditorInputModes,
|
5547
5521
|
EditorState3 as EditorState,
|
5522
|
+
EditorToolbar,
|
5548
5523
|
EditorView21 as EditorView,
|
5549
5524
|
EditorViewMode,
|
5550
5525
|
EditorViewModes,
|
@@ -5554,7 +5529,6 @@ export {
|
|
5554
5529
|
RemoteSelectionsDecorator,
|
5555
5530
|
SpaceAwarenessProvider,
|
5556
5531
|
TextKind,
|
5557
|
-
Toolbar,
|
5558
5532
|
addBlockquote,
|
5559
5533
|
addCodeblock,
|
5560
5534
|
addLink,
|
@@ -5573,8 +5547,10 @@ export {
|
|
5573
5547
|
commentsState,
|
5574
5548
|
convertTreeToJson,
|
5575
5549
|
createBasicExtensions,
|
5576
|
-
createComment,
|
5550
|
+
createComment2 as createComment,
|
5577
5551
|
createDataExtensions,
|
5552
|
+
createEditorAction,
|
5553
|
+
createEditorActionGroup,
|
5578
5554
|
createEditorStateStore,
|
5579
5555
|
createEditorStateTransaction,
|
5580
5556
|
createElement,
|
@@ -5613,7 +5589,7 @@ export {
|
|
5613
5589
|
mention,
|
5614
5590
|
overlap,
|
5615
5591
|
preventNewline,
|
5616
|
-
|
5592
|
+
processEditorPayload,
|
5617
5593
|
removeBlockquote,
|
5618
5594
|
removeCodeblock,
|
5619
5595
|
removeLink,
|
@@ -5629,6 +5605,8 @@ export {
|
|
5629
5605
|
setSelection,
|
5630
5606
|
setStyle,
|
5631
5607
|
singleValueFacet,
|
5608
|
+
stackItemContentEditorClassNames,
|
5609
|
+
stackItemContentToolbarClassNames,
|
5632
5610
|
table,
|
5633
5611
|
tags2 as tags,
|
5634
5612
|
textRange,
|
@@ -5646,9 +5624,9 @@ export {
|
|
5646
5624
|
useCommentClickListener,
|
5647
5625
|
useCommentState,
|
5648
5626
|
useComments,
|
5627
|
+
useEditorToolbarState,
|
5649
5628
|
useFormattingState,
|
5650
5629
|
useTextEditor,
|
5651
|
-
useToolbarContext,
|
5652
5630
|
wrapWithCatch
|
5653
5631
|
};
|
5654
5632
|
//# sourceMappingURL=index.mjs.map
|